xref: /aosp_15_r20/external/webrtc/pc/peer_connection_jsep_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include <stddef.h>
12 
13 #include <algorithm>
14 #include <map>
15 #include <memory>
16 #include <string>
17 #include <tuple>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/strings/string_view.h"
22 #include "absl/types/optional.h"
23 #include "api/call/call_factory_interface.h"
24 #include "api/field_trials_view.h"
25 #include "api/jsep.h"
26 #include "api/media_stream_interface.h"
27 #include "api/media_types.h"
28 #include "api/peer_connection_interface.h"
29 #include "api/rtc_error.h"
30 #include "api/rtp_parameters.h"
31 #include "api/rtp_receiver_interface.h"
32 #include "api/rtp_sender_interface.h"
33 #include "api/rtp_transceiver_direction.h"
34 #include "api/rtp_transceiver_interface.h"
35 #include "api/scoped_refptr.h"
36 #include "api/task_queue/default_task_queue_factory.h"
37 #include "api/task_queue/task_queue_factory.h"
38 #include "api/transport/field_trial_based_config.h"
39 #include "api/transport/sctp_transport_factory_interface.h"
40 #include "media/base/media_engine.h"
41 #include "media/base/stream_params.h"
42 #include "media/engine/webrtc_media_engine.h"
43 #include "media/engine/webrtc_media_engine_defaults.h"
44 #include "modules/audio_device/include/audio_device.h"
45 #include "p2p/base/p2p_constants.h"
46 #include "p2p/base/port_allocator.h"
47 #include "p2p/base/transport_info.h"
48 #include "pc/channel_interface.h"
49 #include "pc/media_session.h"
50 #include "pc/peer_connection_wrapper.h"
51 #include "pc/sdp_utils.h"
52 #include "pc/session_description.h"
53 #include "pc/test/mock_peer_connection_observers.h"
54 #include "rtc_base/rtc_certificate_generator.h"
55 #include "rtc_base/thread.h"
56 #include "test/gtest.h"
57 #ifdef WEBRTC_ANDROID
58 #include "pc/test/android_test_initializer.h"
59 #endif
60 #include "pc/test/fake_audio_capture_module.h"
61 #include "rtc_base/virtual_socket_server.h"
62 #include "test/gmock.h"
63 #include "test/pc/sctp/fake_sctp_transport.h"
64 
65 // This file contains tests that ensure the PeerConnection's implementation of
66 // CreateOffer/CreateAnswer/SetLocalDescription/SetRemoteDescription conform
67 // to the JavaScript Session Establishment Protocol (JSEP).
68 // For now these semantics are only available when configuring the
69 // PeerConnection with Unified Plan, but eventually that will be the default.
70 
71 namespace webrtc {
72 
73 using cricket::MediaContentDescription;
74 using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
75 using ::testing::Combine;
76 using ::testing::ElementsAre;
77 using ::testing::UnorderedElementsAre;
78 using ::testing::Values;
79 
CreatePeerConnectionFactoryDependencies()80 PeerConnectionFactoryDependencies CreatePeerConnectionFactoryDependencies() {
81   PeerConnectionFactoryDependencies dependencies;
82   dependencies.worker_thread = rtc::Thread::Current();
83   dependencies.network_thread = rtc::Thread::Current();
84   dependencies.signaling_thread = rtc::Thread::Current();
85   dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
86   dependencies.trials = std::make_unique<FieldTrialBasedConfig>();
87   cricket::MediaEngineDependencies media_deps;
88   media_deps.task_queue_factory = dependencies.task_queue_factory.get();
89   media_deps.adm = FakeAudioCaptureModule::Create();
90   media_deps.trials = dependencies.trials.get();
91   SetMediaEngineDefaults(&media_deps);
92   dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
93   dependencies.call_factory = CreateCallFactory();
94   dependencies.sctp_factory = std::make_unique<FakeSctpTransportFactory>();
95   return dependencies;
96 }
97 
98 class PeerConnectionJsepTest : public ::testing::Test {
99  protected:
100   typedef std::unique_ptr<PeerConnectionWrapper> WrapperPtr;
101 
PeerConnectionJsepTest()102   PeerConnectionJsepTest()
103       : vss_(new rtc::VirtualSocketServer()), main_(vss_.get()) {
104 #ifdef WEBRTC_ANDROID
105     InitializeAndroidObjects();
106 #endif
107   }
108 
CreatePeerConnection()109   WrapperPtr CreatePeerConnection() {
110     RTCConfiguration config;
111     config.sdp_semantics = SdpSemantics::kUnifiedPlan;
112     return CreatePeerConnection(config);
113   }
114 
CreatePeerConnection(const RTCConfiguration & config)115   WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
116     rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory =
117         CreateModularPeerConnectionFactory(
118             CreatePeerConnectionFactoryDependencies());
119     auto observer = std::make_unique<MockPeerConnectionObserver>();
120     auto result = pc_factory->CreatePeerConnectionOrError(
121         config, PeerConnectionDependencies(observer.get()));
122     if (!result.ok()) {
123       return nullptr;
124     }
125 
126     observer->SetPeerConnectionInterface(result.value().get());
127     return std::make_unique<PeerConnectionWrapper>(
128         pc_factory, result.MoveValue(), std::move(observer));
129   }
130 
131   std::unique_ptr<rtc::VirtualSocketServer> vss_;
132   rtc::AutoSocketServerThread main_;
133 };
134 
135 // Tests for JSEP initial offer generation.
136 
137 // Test that an offer created by a PeerConnection with no transceivers generates
138 // no media sections.
TEST_F(PeerConnectionJsepTest,EmptyInitialOffer)139 TEST_F(PeerConnectionJsepTest, EmptyInitialOffer) {
140   auto caller = CreatePeerConnection();
141 
142   auto offer = caller->CreateOffer();
143   ASSERT_EQ(0u, offer->description()->contents().size());
144 }
145 
146 // Test that an initial offer with one audio track generates one audio media
147 // section.
TEST_F(PeerConnectionJsepTest,AudioOnlyInitialOffer)148 TEST_F(PeerConnectionJsepTest, AudioOnlyInitialOffer) {
149   auto caller = CreatePeerConnection();
150   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
151 
152   auto offer = caller->CreateOffer();
153   auto contents = offer->description()->contents();
154   ASSERT_EQ(1u, contents.size());
155   EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, contents[0].media_description()->type());
156 }
157 
158 // Test than an initial offer with one video track generates one video media
159 // section
TEST_F(PeerConnectionJsepTest,VideoOnlyInitialOffer)160 TEST_F(PeerConnectionJsepTest, VideoOnlyInitialOffer) {
161   auto caller = CreatePeerConnection();
162   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
163 
164   auto offer = caller->CreateOffer();
165   auto contents = offer->description()->contents();
166   ASSERT_EQ(1u, contents.size());
167   EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, contents[0].media_description()->type());
168 }
169 
170 // Test that an initial offer with one data channel generates one data media
171 // section.
TEST_F(PeerConnectionJsepTest,DataOnlyInitialOffer)172 TEST_F(PeerConnectionJsepTest, DataOnlyInitialOffer) {
173   auto caller = CreatePeerConnection();
174   caller->CreateDataChannel("dc");
175 
176   auto offer = caller->CreateOffer();
177   auto contents = offer->description()->contents();
178   ASSERT_EQ(1u, contents.size());
179   EXPECT_EQ(cricket::MEDIA_TYPE_DATA, contents[0].media_description()->type());
180 }
181 
182 // Test that creating multiple data channels only results in one data section
183 // generated in the offer.
TEST_F(PeerConnectionJsepTest,MultipleDataChannelsCreateOnlyOneDataSection)184 TEST_F(PeerConnectionJsepTest, MultipleDataChannelsCreateOnlyOneDataSection) {
185   auto caller = CreatePeerConnection();
186   caller->CreateDataChannel("first");
187   caller->CreateDataChannel("second");
188   caller->CreateDataChannel("third");
189 
190   auto offer = caller->CreateOffer();
191   ASSERT_EQ(1u, offer->description()->contents().size());
192 }
193 
194 // Test that multiple media sections in the initial offer are ordered in the
195 // order the transceivers were added to the PeerConnection. This is required by
196 // JSEP section 5.2.1.
TEST_F(PeerConnectionJsepTest,MediaSectionsInInitialOfferOrderedCorrectly)197 TEST_F(PeerConnectionJsepTest, MediaSectionsInInitialOfferOrderedCorrectly) {
198   auto caller = CreatePeerConnection();
199   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
200   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
201   RtpTransceiverInit init;
202   init.direction = RtpTransceiverDirection::kSendOnly;
203   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
204 
205   auto offer = caller->CreateOffer();
206   auto contents = offer->description()->contents();
207   ASSERT_EQ(3u, contents.size());
208 
209   const MediaContentDescription* media_description1 =
210       contents[0].media_description();
211   EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, media_description1->type());
212   EXPECT_EQ(RtpTransceiverDirection::kSendRecv,
213             media_description1->direction());
214 
215   const MediaContentDescription* media_description2 =
216       contents[1].media_description();
217   EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, media_description2->type());
218   EXPECT_EQ(RtpTransceiverDirection::kSendRecv,
219             media_description2->direction());
220 
221   const MediaContentDescription* media_description3 =
222       contents[2].media_description();
223   EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, media_description3->type());
224   EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
225             media_description3->direction());
226 }
227 
228 // Test that media sections in the initial offer have different mids.
TEST_F(PeerConnectionJsepTest,MediaSectionsInInitialOfferHaveDifferentMids)229 TEST_F(PeerConnectionJsepTest, MediaSectionsInInitialOfferHaveDifferentMids) {
230   auto caller = CreatePeerConnection();
231   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
232   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
233 
234   auto offer = caller->CreateOffer();
235   auto contents = offer->description()->contents();
236   ASSERT_EQ(2u, contents.size());
237   EXPECT_NE(contents[0].name, contents[1].name);
238 }
239 
TEST_F(PeerConnectionJsepTest,StoppedTransceiverHasNoMediaSectionInInitialOffer)240 TEST_F(PeerConnectionJsepTest,
241        StoppedTransceiverHasNoMediaSectionInInitialOffer) {
242   auto caller = CreatePeerConnection();
243   auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
244   transceiver->StopInternal();
245 
246   auto offer = caller->CreateOffer();
247   EXPECT_EQ(0u, offer->description()->contents().size());
248 }
249 
250 // Tests for JSEP SetLocalDescription with a local offer.
251 
TEST_F(PeerConnectionJsepTest,SetLocalEmptyOfferCreatesNoTransceivers)252 TEST_F(PeerConnectionJsepTest, SetLocalEmptyOfferCreatesNoTransceivers) {
253   auto caller = CreatePeerConnection();
254 
255   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
256 
257   EXPECT_THAT(caller->pc()->GetTransceivers(), ElementsAre());
258   EXPECT_THAT(caller->pc()->GetSenders(), ElementsAre());
259   EXPECT_THAT(caller->pc()->GetReceivers(), ElementsAre());
260 }
261 
TEST_F(PeerConnectionJsepTest,SetLocalOfferSetsTransceiverMid)262 TEST_F(PeerConnectionJsepTest, SetLocalOfferSetsTransceiverMid) {
263   auto caller = CreatePeerConnection();
264   auto audio_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
265   auto video_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
266 
267   auto offer = caller->CreateOffer();
268   std::string audio_mid = offer->description()->contents()[0].name;
269   std::string video_mid = offer->description()->contents()[1].name;
270 
271   ASSERT_TRUE(caller->SetLocalDescription(std::move(offer)));
272 
273   EXPECT_EQ(audio_mid, audio_transceiver->mid());
274   EXPECT_EQ(video_mid, video_transceiver->mid());
275 }
276 
277 // Tests for JSEP SetRemoteDescription with a remote offer.
278 
279 // Test that setting a remote offer with sendrecv audio and video creates two
280 // transceivers, one for receiving audio and one for receiving video.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferCreatesTransceivers)281 TEST_F(PeerConnectionJsepTest, SetRemoteOfferCreatesTransceivers) {
282   auto caller = CreatePeerConnection();
283   auto caller_audio = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
284   auto caller_video = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
285   auto callee = CreatePeerConnection();
286 
287   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
288 
289   auto transceivers = callee->pc()->GetTransceivers();
290   ASSERT_EQ(2u, transceivers.size());
291 
292   EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, transceivers[0]->media_type());
293   EXPECT_EQ(caller_audio->mid(), transceivers[0]->mid());
294   EXPECT_EQ(RtpTransceiverDirection::kRecvOnly, transceivers[0]->direction());
295   EXPECT_EQ(0u, transceivers[0]->sender()->stream_ids().size());
296 
297   EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, transceivers[1]->media_type());
298   EXPECT_EQ(caller_video->mid(), transceivers[1]->mid());
299   EXPECT_EQ(RtpTransceiverDirection::kRecvOnly, transceivers[1]->direction());
300   EXPECT_EQ(0u, transceivers[1]->sender()->stream_ids().size());
301 }
302 
303 // Test that setting a remote offer with an audio track will reuse the
304 // transceiver created for a local audio track added by AddTrack.
305 // This is specified in JSEP section 5.10 (Applying a Remote Description). The
306 // intent is to preserve backwards compatibility with clients who only use the
307 // AddTrack API.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferReusesTransceiverFromAddTrack)308 TEST_F(PeerConnectionJsepTest, SetRemoteOfferReusesTransceiverFromAddTrack) {
309   auto caller = CreatePeerConnection();
310   caller->AddAudioTrack("a");
311   auto caller_audio = caller->pc()->GetTransceivers()[0];
312   auto callee = CreatePeerConnection();
313   callee->AddAudioTrack("a");
314 
315   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
316 
317   auto transceivers = callee->pc()->GetTransceivers();
318   ASSERT_EQ(1u, transceivers.size());
319   EXPECT_EQ(MediaStreamTrackInterface::kAudioKind,
320             transceivers[0]->receiver()->track()->kind());
321   EXPECT_EQ(caller_audio->mid(), transceivers[0]->mid());
322 }
323 
324 // Test that setting a remote offer with an audio track marked sendonly will not
325 // reuse a transceiver created by AddTrack. JSEP only allows the transceiver to
326 // be reused if the offer direction is sendrecv or recvonly.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferDoesNotReuseTransceiverIfDirectionSendOnly)327 TEST_F(PeerConnectionJsepTest,
328        SetRemoteOfferDoesNotReuseTransceiverIfDirectionSendOnly) {
329   auto caller = CreatePeerConnection();
330   caller->AddAudioTrack("a");
331   auto caller_audio = caller->pc()->GetTransceivers()[0];
332   caller_audio->SetDirectionWithError(RtpTransceiverDirection::kSendOnly);
333   auto callee = CreatePeerConnection();
334   callee->AddAudioTrack("a");
335 
336   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
337 
338   auto transceivers = callee->pc()->GetTransceivers();
339   ASSERT_EQ(2u, transceivers.size());
340   EXPECT_EQ(absl::nullopt, transceivers[0]->mid());
341   EXPECT_EQ(caller_audio->mid(), transceivers[1]->mid());
342 }
343 
344 // Test that setting a remote offer with an audio track will not reuse a
345 // transceiver added by AddTransceiver. The logic for reusing a transceiver is
346 // specific to those added by AddTrack and is tested above.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferDoesNotReuseTransceiverFromAddTransceiver)347 TEST_F(PeerConnectionJsepTest,
348        SetRemoteOfferDoesNotReuseTransceiverFromAddTransceiver) {
349   auto caller = CreatePeerConnection();
350   caller->AddAudioTrack("a");
351   auto callee = CreatePeerConnection();
352   auto transceiver = callee->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
353 
354   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
355 
356   auto transceivers = callee->pc()->GetTransceivers();
357   ASSERT_EQ(2u, transceivers.size());
358   EXPECT_EQ(absl::nullopt, transceivers[0]->mid());
359   EXPECT_EQ(caller->pc()->GetTransceivers()[0]->mid(), transceivers[1]->mid());
360   EXPECT_EQ(MediaStreamTrackInterface::kAudioKind,
361             transceivers[1]->receiver()->track()->kind());
362 }
363 
364 // Test that setting a remote offer with an audio track will not reuse a
365 // transceiver created for a local video track added by AddTrack.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferDoesNotReuseTransceiverOfWrongType)366 TEST_F(PeerConnectionJsepTest,
367        SetRemoteOfferDoesNotReuseTransceiverOfWrongType) {
368   auto caller = CreatePeerConnection();
369   caller->AddAudioTrack("a");
370   auto callee = CreatePeerConnection();
371   auto video_sender = callee->AddVideoTrack("v");
372 
373   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
374 
375   auto transceivers = callee->pc()->GetTransceivers();
376   ASSERT_EQ(2u, transceivers.size());
377   EXPECT_EQ(absl::nullopt, transceivers[0]->mid());
378   EXPECT_EQ(caller->pc()->GetTransceivers()[0]->mid(), transceivers[1]->mid());
379   EXPECT_EQ(MediaStreamTrackInterface::kAudioKind,
380             transceivers[1]->receiver()->track()->kind());
381 }
382 
383 // Test that setting a remote offer with an audio track will not reuse a
384 // stopped transceiver.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferDoesNotReuseStoppedTransceiver)385 TEST_F(PeerConnectionJsepTest, SetRemoteOfferDoesNotReuseStoppedTransceiver) {
386   auto caller = CreatePeerConnection();
387   caller->AddAudioTrack("a");
388   auto callee = CreatePeerConnection();
389   callee->AddAudioTrack("a");
390   callee->pc()->GetTransceivers()[0]->StopInternal();
391 
392   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
393 
394   auto transceivers = callee->pc()->GetTransceivers();
395   ASSERT_EQ(2u, transceivers.size());
396   // The stopped transceiver is removed in SetLocalDescription(answer)
397   ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
398   transceivers = callee->pc()->GetTransceivers();
399   ASSERT_EQ(1u, transceivers.size());
400   EXPECT_EQ(caller->pc()->GetTransceivers()[0]->mid(), transceivers[0]->mid());
401   EXPECT_FALSE(transceivers[0]->stopped());
402 }
403 
404 // Test that audio and video transceivers created on the remote side with
405 // AddTrack will all be reused if there is the same number of audio/video tracks
406 // in the remote offer. Additionally, this tests that transceivers are
407 // successfully matched even if they are in a different order on the remote
408 // side.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferReusesTransceiversOfBothTypes)409 TEST_F(PeerConnectionJsepTest, SetRemoteOfferReusesTransceiversOfBothTypes) {
410   auto caller = CreatePeerConnection();
411   caller->AddVideoTrack("v");
412   caller->AddAudioTrack("a");
413   auto callee = CreatePeerConnection();
414   callee->AddAudioTrack("a");
415   callee->AddVideoTrack("v");
416 
417   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
418 
419   auto caller_transceivers = caller->pc()->GetTransceivers();
420   auto callee_transceivers = callee->pc()->GetTransceivers();
421   ASSERT_EQ(2u, callee_transceivers.size());
422   EXPECT_EQ(caller_transceivers[0]->mid(), callee_transceivers[1]->mid());
423   EXPECT_EQ(caller_transceivers[1]->mid(), callee_transceivers[0]->mid());
424 }
425 
426 // Tests for JSEP initial CreateAnswer.
427 
428 // Test that the answer to a remote offer creates media sections for each
429 // offered media in the same order and with the same mids.
TEST_F(PeerConnectionJsepTest,CreateAnswerHasSameMidsAsOffer)430 TEST_F(PeerConnectionJsepTest, CreateAnswerHasSameMidsAsOffer) {
431   auto caller = CreatePeerConnection();
432   auto first_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
433   auto second_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
434   auto third_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
435   caller->CreateDataChannel("dc");
436   auto callee = CreatePeerConnection();
437 
438   auto offer = caller->CreateOffer();
439   const auto* offer_data = cricket::GetFirstDataContent(offer->description());
440   ASSERT_TRUE(
441       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
442   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
443 
444   auto answer = callee->CreateAnswer();
445   auto contents = answer->description()->contents();
446   ASSERT_EQ(4u, contents.size());
447   EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, contents[0].media_description()->type());
448   EXPECT_EQ(first_transceiver->mid(), contents[0].name);
449   EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, contents[1].media_description()->type());
450   EXPECT_EQ(second_transceiver->mid(), contents[1].name);
451   EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, contents[2].media_description()->type());
452   EXPECT_EQ(third_transceiver->mid(), contents[2].name);
453   EXPECT_EQ(cricket::MEDIA_TYPE_DATA, contents[3].media_description()->type());
454   EXPECT_EQ(offer_data->name, contents[3].name);
455 }
456 
457 // Test that an answering media section is marked as rejected if the underlying
458 // transceiver has been stopped.
TEST_F(PeerConnectionJsepTest,CreateAnswerRejectsStoppedTransceiver)459 TEST_F(PeerConnectionJsepTest, CreateAnswerRejectsStoppedTransceiver) {
460   auto caller = CreatePeerConnection();
461   caller->AddAudioTrack("a");
462   auto callee = CreatePeerConnection();
463 
464   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
465 
466   callee->pc()->GetTransceivers()[0]->StopInternal();
467 
468   auto answer = callee->CreateAnswer();
469   auto contents = answer->description()->contents();
470   ASSERT_EQ(1u, contents.size());
471   EXPECT_TRUE(contents[0].rejected);
472 }
473 
474 // Test that CreateAnswer will generate media sections which will only send or
475 // receive if the offer indicates it can do the reciprocating direction.
476 // The full matrix is tested more extensively in MediaSession.
TEST_F(PeerConnectionJsepTest,CreateAnswerNegotiatesDirection)477 TEST_F(PeerConnectionJsepTest, CreateAnswerNegotiatesDirection) {
478   auto caller = CreatePeerConnection();
479   RtpTransceiverInit init;
480   init.direction = RtpTransceiverDirection::kSendOnly;
481   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
482   auto callee = CreatePeerConnection();
483   callee->AddAudioTrack("a");
484 
485   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
486 
487   auto answer = callee->CreateAnswer();
488   auto contents = answer->description()->contents();
489   ASSERT_EQ(1u, contents.size());
490   EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
491             contents[0].media_description()->direction());
492 }
493 
494 // Tests for JSEP SetLocalDescription with a local answer.
495 // Note that these test only the additional behaviors not covered by
496 // SetLocalDescription with a local offer.
497 
498 // Test that SetLocalDescription with an answer sets the current_direction
499 // property of the transceivers mentioned in the session description.
TEST_F(PeerConnectionJsepTest,SetLocalAnswerUpdatesCurrentDirection)500 TEST_F(PeerConnectionJsepTest, SetLocalAnswerUpdatesCurrentDirection) {
501   auto caller = CreatePeerConnection();
502   auto caller_audio = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
503   caller_audio->SetDirectionWithError(RtpTransceiverDirection::kRecvOnly);
504   auto callee = CreatePeerConnection();
505   callee->AddAudioTrack("a");
506 
507   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
508   ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
509 
510   auto transceivers = callee->pc()->GetTransceivers();
511   ASSERT_EQ(1u, transceivers.size());
512   // Since the offer was recvonly and the transceiver direction is sendrecv,
513   // the negotiated direction will be sendonly.
514   EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
515             transceivers[0]->current_direction());
516 }
517 
518 // Tests for JSEP SetRemoteDescription with a remote answer.
519 // Note that these test only the additional behaviors not covered by
520 // SetRemoteDescription with a remote offer.
521 
TEST_F(PeerConnectionJsepTest,SetRemoteAnswerUpdatesCurrentDirection)522 TEST_F(PeerConnectionJsepTest, SetRemoteAnswerUpdatesCurrentDirection) {
523   auto caller = CreatePeerConnection();
524   caller->AddAudioTrack("a");
525   auto callee = CreatePeerConnection();
526   callee->AddAudioTrack("a");
527   auto callee_audio = callee->pc()->GetTransceivers()[0];
528   callee_audio->SetDirectionWithError(RtpTransceiverDirection::kSendOnly);
529 
530   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
531   ASSERT_TRUE(
532       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
533 
534   auto transceivers = caller->pc()->GetTransceivers();
535   ASSERT_EQ(1u, transceivers.size());
536   // Since the remote transceiver was set to sendonly, the negotiated direction
537   // in the answer would be sendonly which we apply as recvonly to the local
538   // transceiver.
539   EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
540             transceivers[0]->current_direction());
541 }
542 
TEST_F(PeerConnectionJsepTest,ChangeDirectionFromRecvOnlyToSendRecvDoesNotBreakVideoNegotiation)543 TEST_F(PeerConnectionJsepTest,
544        ChangeDirectionFromRecvOnlyToSendRecvDoesNotBreakVideoNegotiation) {
545   auto caller = CreatePeerConnection();
546   auto caller_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
547   auto callee = CreatePeerConnection();
548   caller_transceiver->SetDirectionWithError(RtpTransceiverDirection::kRecvOnly);
549 
550   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
551   ASSERT_TRUE(
552       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
553 
554   caller_transceiver->SetDirectionWithError(RtpTransceiverDirection::kSendRecv);
555 
556   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
557   ASSERT_TRUE(
558       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
559 }
560 
TEST_F(PeerConnectionJsepTest,ChangeDirectionFromRecvOnlyToSendRecvDoesNotBreakAudioNegotiation)561 TEST_F(PeerConnectionJsepTest,
562        ChangeDirectionFromRecvOnlyToSendRecvDoesNotBreakAudioNegotiation) {
563   auto caller = CreatePeerConnection();
564   auto caller_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
565   auto callee = CreatePeerConnection();
566   caller_transceiver->SetDirectionWithError(RtpTransceiverDirection::kRecvOnly);
567 
568   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
569   ASSERT_TRUE(
570       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
571 
572   caller_transceiver->SetDirectionWithError(RtpTransceiverDirection::kSendRecv);
573 
574   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
575   ASSERT_TRUE(
576       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
577 }
578 
579 // Tests for multiple round trips.
580 
581 // Test that setting a transceiver with the inactive direction does not stop it
582 // on either the caller or the callee.
TEST_F(PeerConnectionJsepTest,SettingTransceiverInactiveDoesNotStopIt)583 TEST_F(PeerConnectionJsepTest, SettingTransceiverInactiveDoesNotStopIt) {
584   auto caller = CreatePeerConnection();
585   caller->AddAudioTrack("a");
586   auto callee = CreatePeerConnection();
587   callee->AddAudioTrack("a");
588   callee->pc()->GetTransceivers()[0]->SetDirectionWithError(
589       RtpTransceiverDirection::kInactive);
590 
591   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
592   ASSERT_TRUE(
593       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
594 
595   EXPECT_FALSE(caller->pc()->GetTransceivers()[0]->stopped());
596   EXPECT_FALSE(callee->pc()->GetTransceivers()[0]->stopped());
597 }
598 
599 // Test that if a transceiver had been associated and later stopped, then a
600 // media section is still generated for it and the media section is marked as
601 // rejected.
TEST_F(PeerConnectionJsepTest,ReOfferMediaSectionForAssociatedStoppedTransceiverIsRejected)602 TEST_F(PeerConnectionJsepTest,
603        ReOfferMediaSectionForAssociatedStoppedTransceiverIsRejected) {
604   auto caller = CreatePeerConnection();
605   auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
606   auto callee = CreatePeerConnection();
607 
608   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
609   ASSERT_TRUE(
610       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
611 
612   ASSERT_TRUE(transceiver->mid());
613   transceiver->StopInternal();
614 
615   auto reoffer = caller->CreateOffer();
616   auto contents = reoffer->description()->contents();
617   ASSERT_EQ(1u, contents.size());
618   EXPECT_TRUE(contents[0].rejected);
619 }
620 
621 // Test that stopping an associated transceiver on the caller side will stop the
622 // corresponding transceiver on the remote side when the remote offer is
623 // applied.
TEST_F(PeerConnectionJsepTest,StoppingTransceiverInOfferStopsTransceiverOnRemoteSide)624 TEST_F(PeerConnectionJsepTest,
625        StoppingTransceiverInOfferStopsTransceiverOnRemoteSide) {
626   auto caller = CreatePeerConnection();
627   auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
628   auto callee = CreatePeerConnection();
629 
630   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
631   ASSERT_TRUE(
632       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
633 
634   transceiver->StopInternal();
635 
636   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
637 
638   auto transceivers = callee->pc()->GetTransceivers();
639   EXPECT_EQ(1u, transceivers.size());
640   ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
641   transceivers = callee->pc()->GetTransceivers();
642   EXPECT_EQ(0u, transceivers.size());
643 }
644 
645 // Test that CreateOffer will only generate a recycled media section if the
646 // transceiver to be recycled has been seen stopped by the other side first.
TEST_F(PeerConnectionJsepTest,CreateOfferDoesNotRecycleMediaSectionIfFirstStopped)647 TEST_F(PeerConnectionJsepTest,
648        CreateOfferDoesNotRecycleMediaSectionIfFirstStopped) {
649   auto caller = CreatePeerConnection();
650   auto first_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
651   auto callee = CreatePeerConnection();
652 
653   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
654   ASSERT_TRUE(
655       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
656 
657   auto second_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
658   first_transceiver->StopInternal();
659 
660   auto reoffer = caller->CreateOffer();
661   auto contents = reoffer->description()->contents();
662   ASSERT_EQ(2u, contents.size());
663   EXPECT_TRUE(contents[0].rejected);
664   EXPECT_FALSE(contents[1].rejected);
665 }
666 
667 // Test that the offer/answer and the transceivers are correctly generated and
668 // updated when the media section is recycled after the callee stops a
669 // transceiver and sends an answer with a 0 port.
TEST_F(PeerConnectionJsepTest,RecycleMediaSectionWhenStoppingTransceiverOnAnswerer)670 TEST_F(PeerConnectionJsepTest,
671        RecycleMediaSectionWhenStoppingTransceiverOnAnswerer) {
672   auto caller = CreatePeerConnection();
673   auto first_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
674   auto callee = CreatePeerConnection();
675 
676   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
677   std::string first_mid = *first_transceiver->mid();
678   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
679   callee->pc()->GetTransceivers()[0]->StopInternal();
680   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
681   ASSERT_TRUE(
682       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
683   EXPECT_TRUE(first_transceiver->stopped());
684   // First transceivers are dissociated on caller side.
685   ASSERT_EQ(absl::nullopt, first_transceiver->mid());
686   // They are disassociated on callee side.
687   ASSERT_EQ(0u, callee->pc()->GetTransceivers().size());
688 
689   // New offer exchange with new transceivers that recycles the m section
690   // correctly.
691   caller->AddAudioTrack("audio2");
692   callee->AddAudioTrack("audio2");
693   auto offer = caller->CreateOffer();
694   auto offer_contents = offer->description()->contents();
695   std::string second_mid = offer_contents[0].name;
696   ASSERT_EQ(1u, offer_contents.size());
697   EXPECT_FALSE(offer_contents[0].rejected);
698   EXPECT_NE(first_mid, second_mid);
699 
700   // Setting the offer on each side will dissociate the first transceivers and
701   // associate the new transceivers.
702   ASSERT_TRUE(
703       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
704   EXPECT_EQ(absl::nullopt, first_transceiver->mid());
705   ASSERT_EQ(1u, caller->pc()->GetTransceivers().size());
706   EXPECT_EQ(second_mid, caller->pc()->GetTransceivers()[0]->mid());
707   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
708   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
709   EXPECT_EQ(second_mid, callee->pc()->GetTransceivers()[0]->mid());
710 
711   // The new answer should also recycle the m section correctly.
712   auto answer = callee->CreateAnswer();
713   auto answer_contents = answer->description()->contents();
714   ASSERT_EQ(1u, answer_contents.size());
715   EXPECT_FALSE(answer_contents[0].rejected);
716   EXPECT_EQ(second_mid, answer_contents[0].name);
717 
718   // Finishing the negotiation shouldn't add or dissociate any transceivers.
719   ASSERT_TRUE(
720       callee->SetLocalDescription(CloneSessionDescription(answer.get())));
721   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
722   auto caller_transceivers = caller->pc()->GetTransceivers();
723   ASSERT_EQ(1u, caller_transceivers.size());
724   EXPECT_EQ(second_mid, caller_transceivers[0]->mid());
725   auto callee_transceivers = callee->pc()->GetTransceivers();
726   ASSERT_EQ(1u, callee_transceivers.size());
727   EXPECT_EQ(second_mid, callee_transceivers[0]->mid());
728 }
729 
730 // Test that creating/setting a local offer that recycles an m= section is
731 // idempotent.
TEST_F(PeerConnectionJsepTest,CreateOfferRecyclesWhenOfferingTwice)732 TEST_F(PeerConnectionJsepTest, CreateOfferRecyclesWhenOfferingTwice) {
733   // Do a negotiation with a port 0 for the media section.
734   auto caller = CreatePeerConnection();
735   auto first_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
736   auto callee = CreatePeerConnection();
737   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
738   first_transceiver->StopInternal();
739   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
740   caller->AddAudioTrack("audio2");
741 
742   // Create a new offer that recycles the media section and set it as a local
743   // description.
744   auto offer = caller->CreateOffer();
745   auto offer_contents = offer->description()->contents();
746   ASSERT_EQ(1u, offer_contents.size());
747   EXPECT_FALSE(offer_contents[0].rejected);
748   ASSERT_TRUE(caller->SetLocalDescription(std::move(offer)));
749   ASSERT_EQ(1u, caller->pc()->GetTransceivers().size());
750   EXPECT_FALSE(caller->pc()->GetTransceivers()[0]->stopped());
751   std::string second_mid = offer_contents[0].name;
752 
753   // Create another new offer and set the local description again without the
754   // rest of any negotation ocurring.
755   auto second_offer = caller->CreateOffer();
756   auto second_offer_contents = second_offer->description()->contents();
757   ASSERT_EQ(1u, second_offer_contents.size());
758   EXPECT_FALSE(second_offer_contents[0].rejected);
759   // The mid shouldn't change.
760   EXPECT_EQ(second_mid, second_offer_contents[0].name);
761 
762   ASSERT_TRUE(caller->SetLocalDescription(std::move(second_offer)));
763   // Make sure that the caller's transceivers are associated correctly.
764   auto caller_transceivers = caller->pc()->GetTransceivers();
765   ASSERT_EQ(1u, caller_transceivers.size());
766   EXPECT_EQ(second_mid, caller_transceivers[0]->mid());
767   EXPECT_FALSE(caller_transceivers[0]->stopped());
768 }
769 
770 // Test that the offer/answer and transceivers for both the caller and callee
771 // side are generated/updated correctly when recycling an audio/video media
772 // section as a media section of either the same or opposite type.
773 // Correct recycling works as follows:
774 // - The m= section is re-offered with a new MID value and the new media type.
775 // - The previously-associated transceiver is dissociated when the new offer is
776 //   set as a local description on the offerer or as a remote description on
777 //   the answerer.
778 // - The new transceiver is associated with the new MID value.
779 class RecycleMediaSectionTest
780     : public PeerConnectionJsepTest,
781       public ::testing::WithParamInterface<
782           std::tuple<cricket::MediaType, cricket::MediaType>> {
783  protected:
RecycleMediaSectionTest()784   RecycleMediaSectionTest() {
785     first_type_ = std::get<0>(GetParam());
786     second_type_ = std::get<1>(GetParam());
787   }
788 
789   cricket::MediaType first_type_;
790   cricket::MediaType second_type_;
791 };
792 
793 // Test that recycling works properly when a new transceiver recycles an m=
794 // section that was rejected in both the current local and remote descriptions.
TEST_P(RecycleMediaSectionTest,CurrentLocalAndCurrentRemoteRejected)795 TEST_P(RecycleMediaSectionTest, CurrentLocalAndCurrentRemoteRejected) {
796   auto caller = CreatePeerConnection();
797   auto first_transceiver = caller->AddTransceiver(first_type_);
798   auto callee = CreatePeerConnection();
799 
800   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
801 
802   std::string first_mid = *first_transceiver->mid();
803   first_transceiver->StopInternal();
804 
805   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
806 
807   auto second_transceiver = caller->AddTransceiver(second_type_);
808 
809   // The offer should reuse the previous media section but allocate a new MID
810   // and change the media type.
811   auto offer = caller->CreateOffer();
812   auto offer_contents = offer->description()->contents();
813   ASSERT_EQ(1u, offer_contents.size());
814   EXPECT_FALSE(offer_contents[0].rejected);
815   EXPECT_EQ(second_type_, offer_contents[0].media_description()->type());
816   std::string second_mid = offer_contents[0].name;
817   EXPECT_NE(first_mid, second_mid);
818 
819   // Setting the local offer will dissociate the previous transceiver and set
820   // the MID for the new transceiver.
821   ASSERT_TRUE(
822       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
823   EXPECT_EQ(absl::nullopt, first_transceiver->mid());
824   EXPECT_EQ(second_mid, second_transceiver->mid());
825 
826   // Setting the remote offer will dissociate the previous transceiver and
827   // create a new transceiver for the media section.
828   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
829   auto callee_transceivers = callee->pc()->GetTransceivers();
830   ASSERT_EQ(1u, callee_transceivers.size());
831   EXPECT_EQ(second_mid, callee_transceivers[0]->mid());
832   EXPECT_EQ(second_type_, callee_transceivers[0]->media_type());
833 
834   // The answer should have only one media section for the new transceiver.
835   auto answer = callee->CreateAnswer();
836   auto answer_contents = answer->description()->contents();
837   ASSERT_EQ(1u, answer_contents.size());
838   EXPECT_FALSE(answer_contents[0].rejected);
839   EXPECT_EQ(second_mid, answer_contents[0].name);
840   EXPECT_EQ(second_type_, answer_contents[0].media_description()->type());
841 
842   // Setting the local answer should succeed.
843   ASSERT_TRUE(
844       callee->SetLocalDescription(CloneSessionDescription(answer.get())));
845 
846   // Setting the remote answer should succeed and not create any new
847   // transceivers.
848   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
849   ASSERT_EQ(1u, caller->pc()->GetTransceivers().size());
850   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
851 }
852 
853 // Test that recycling works properly when a new transceiver recycles an m=
854 // section that was rejected in only the current remote description.
TEST_P(RecycleMediaSectionTest,CurrentRemoteOnlyRejected)855 TEST_P(RecycleMediaSectionTest, CurrentRemoteOnlyRejected) {
856   auto caller = CreatePeerConnection();
857   auto caller_first_transceiver = caller->AddTransceiver(first_type_);
858   auto callee = CreatePeerConnection();
859 
860   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
861 
862   std::string first_mid = *caller_first_transceiver->mid();
863   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
864   auto callee_first_transceiver = callee->pc()->GetTransceivers()[0];
865   callee_first_transceiver->StopInternal();
866 
867   // The answer will have a rejected m= section.
868   ASSERT_TRUE(
869       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
870 
871   // The offer should reuse the previous media section but allocate a new MID
872   // and change the media type.
873   auto caller_second_transceiver = caller->AddTransceiver(second_type_);
874   auto offer = caller->CreateOffer();
875   const auto& offer_contents = offer->description()->contents();
876   ASSERT_EQ(1u, offer_contents.size());
877   EXPECT_FALSE(offer_contents[0].rejected);
878   EXPECT_EQ(second_type_, offer_contents[0].media_description()->type());
879   std::string second_mid = offer_contents[0].name;
880   EXPECT_NE(first_mid, second_mid);
881 
882   // Setting the local offer will dissociate the previous transceiver and set
883   // the MID for the new transceiver.
884   ASSERT_TRUE(
885       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
886   EXPECT_EQ(absl::nullopt, caller_first_transceiver->mid());
887   EXPECT_EQ(second_mid, caller_second_transceiver->mid());
888 
889   // Setting the remote offer will dissociate the previous transceiver and
890   // create a new transceiver for the media section.
891   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
892   auto callee_transceivers = callee->pc()->GetTransceivers();
893   ASSERT_EQ(1u, callee_transceivers.size());
894   EXPECT_EQ(second_mid, callee_transceivers[0]->mid());
895   EXPECT_EQ(second_type_, callee_transceivers[0]->media_type());
896 
897   // The answer should have only one media section for the new transceiver.
898   auto answer = callee->CreateAnswer();
899   auto answer_contents = answer->description()->contents();
900   ASSERT_EQ(1u, answer_contents.size());
901   EXPECT_FALSE(answer_contents[0].rejected);
902   EXPECT_EQ(second_mid, answer_contents[0].name);
903   EXPECT_EQ(second_type_, answer_contents[0].media_description()->type());
904 
905   // Setting the local answer should succeed.
906   ASSERT_TRUE(
907       callee->SetLocalDescription(CloneSessionDescription(answer.get())));
908 
909   // Setting the remote answer should succeed and not create any new
910   // transceivers.
911   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
912   ASSERT_EQ(1u, caller->pc()->GetTransceivers().size());
913   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
914 }
915 
916 // Test that recycling works properly when a new transceiver recycles an m=
917 // section that was rejected only in the current local description.
TEST_P(RecycleMediaSectionTest,CurrentLocalOnlyRejected)918 TEST_P(RecycleMediaSectionTest, CurrentLocalOnlyRejected) {
919   auto caller = CreatePeerConnection();
920   auto caller_first_transceiver = caller->AddTransceiver(first_type_);
921   auto callee = CreatePeerConnection();
922 
923   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
924 
925   std::string first_mid = *caller_first_transceiver->mid();
926   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
927   auto callee_first_transceiver = callee->pc()->GetTransceivers()[0];
928   callee_first_transceiver->StopInternal();
929 
930   // The answer will have a rejected m= section.
931   ASSERT_TRUE(
932       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
933 
934   // The offer should reuse the previous media section but allocate a new MID
935   // and change the media type.
936   auto callee_second_transceiver = callee->AddTransceiver(second_type_);
937   auto offer = callee->CreateOffer();
938   const auto& offer_contents = offer->description()->contents();
939   ASSERT_EQ(1u, offer_contents.size());
940   EXPECT_FALSE(offer_contents[0].rejected);
941   EXPECT_EQ(second_type_, offer_contents[0].media_description()->type());
942   std::string second_mid = offer_contents[0].name;
943   EXPECT_NE(first_mid, second_mid);
944 
945   // Setting the local offer will dissociate the previous transceiver and set
946   // the MID for the new transceiver.
947   ASSERT_TRUE(
948       callee->SetLocalDescription(CloneSessionDescription(offer.get())));
949   EXPECT_EQ(absl::nullopt, callee_first_transceiver->mid());
950   EXPECT_EQ(second_mid, callee_second_transceiver->mid());
951 
952   // Setting the remote offer will dissociate the previous transceiver and
953   // create a new transceiver for the media section.
954   ASSERT_TRUE(caller->SetRemoteDescription(std::move(offer)));
955   auto caller_transceivers = caller->pc()->GetTransceivers();
956   ASSERT_EQ(1u, caller_transceivers.size());
957   EXPECT_EQ(second_mid, caller_transceivers[0]->mid());
958   EXPECT_EQ(second_type_, caller_transceivers[0]->media_type());
959 
960   // The answer should have only one media section for the new transceiver.
961   auto answer = caller->CreateAnswer();
962   auto answer_contents = answer->description()->contents();
963   ASSERT_EQ(1u, answer_contents.size());
964   EXPECT_FALSE(answer_contents[0].rejected);
965   EXPECT_EQ(second_mid, answer_contents[0].name);
966   EXPECT_EQ(second_type_, answer_contents[0].media_description()->type());
967 
968   // Setting the local answer should succeed.
969   ASSERT_TRUE(
970       caller->SetLocalDescription(CloneSessionDescription(answer.get())));
971 
972   // Setting the remote answer should succeed and not create any new
973   // transceivers.
974   ASSERT_TRUE(callee->SetRemoteDescription(std::move(answer)));
975   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
976   ASSERT_EQ(1u, caller->pc()->GetTransceivers().size());
977 }
978 
979 // Test that a m= section is *not* recycled if the media section is only
980 // rejected in the pending local description and there is no current remote
981 // description.
TEST_P(RecycleMediaSectionTest,PendingLocalRejectedAndNoRemote)982 TEST_P(RecycleMediaSectionTest, PendingLocalRejectedAndNoRemote) {
983   auto caller = CreatePeerConnection();
984   auto caller_first_transceiver = caller->AddTransceiver(first_type_);
985 
986   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
987 
988   std::string first_mid = *caller_first_transceiver->mid();
989   caller_first_transceiver->StopInternal();
990 
991   // The reoffer will have a rejected m= section.
992   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
993 
994   auto caller_second_transceiver = caller->AddTransceiver(second_type_);
995 
996   // The reoffer should not recycle the existing m= section since it is not
997   // rejected in either the *current* local or *current* remote description.
998   auto reoffer = caller->CreateOffer();
999   auto reoffer_contents = reoffer->description()->contents();
1000   ASSERT_EQ(2u, reoffer_contents.size());
1001   EXPECT_TRUE(reoffer_contents[0].rejected);
1002   EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type());
1003   EXPECT_EQ(first_mid, reoffer_contents[0].name);
1004   EXPECT_FALSE(reoffer_contents[1].rejected);
1005   EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type());
1006   std::string second_mid = reoffer_contents[1].name;
1007   EXPECT_NE(first_mid, second_mid);
1008 
1009   ASSERT_TRUE(caller->SetLocalDescription(std::move(reoffer)));
1010 
1011   // Both RtpTransceivers are associated.
1012   EXPECT_EQ(first_mid, caller_first_transceiver->mid());
1013   EXPECT_EQ(second_mid, caller_second_transceiver->mid());
1014 }
1015 
1016 // Test that a m= section is *not* recycled if the media section is only
1017 // rejected in the pending local description and not rejected in the current
1018 // remote description.
TEST_P(RecycleMediaSectionTest,PendingLocalRejectedAndNotRejectedRemote)1019 TEST_P(RecycleMediaSectionTest, PendingLocalRejectedAndNotRejectedRemote) {
1020   auto caller = CreatePeerConnection();
1021   auto caller_first_transceiver = caller->AddTransceiver(first_type_);
1022   auto callee = CreatePeerConnection();
1023 
1024   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1025 
1026   std::string first_mid = *caller_first_transceiver->mid();
1027   caller_first_transceiver->StopInternal();
1028 
1029   // The reoffer will have a rejected m= section.
1030   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1031 
1032   auto caller_second_transceiver = caller->AddTransceiver(second_type_);
1033 
1034   // The reoffer should not recycle the existing m= section since it is not
1035   // rejected in either the *current* local or *current* remote description.
1036   auto reoffer = caller->CreateOffer();
1037   auto reoffer_contents = reoffer->description()->contents();
1038   ASSERT_EQ(2u, reoffer_contents.size());
1039   EXPECT_TRUE(reoffer_contents[0].rejected);
1040   EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type());
1041   EXPECT_EQ(first_mid, reoffer_contents[0].name);
1042   EXPECT_FALSE(reoffer_contents[1].rejected);
1043   EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type());
1044   std::string second_mid = reoffer_contents[1].name;
1045   EXPECT_NE(first_mid, second_mid);
1046 
1047   ASSERT_TRUE(caller->SetLocalDescription(std::move(reoffer)));
1048 
1049   // Both RtpTransceivers are associated.
1050   EXPECT_EQ(first_mid, caller_first_transceiver->mid());
1051   EXPECT_EQ(second_mid, caller_second_transceiver->mid());
1052 }
1053 
1054 // Test that an m= section is *not* recycled if the media section is only
1055 // rejected in the pending remote description and there is no current local
1056 // description.
TEST_P(RecycleMediaSectionTest,PendingRemoteRejectedAndNoLocal)1057 TEST_P(RecycleMediaSectionTest, PendingRemoteRejectedAndNoLocal) {
1058   auto caller = CreatePeerConnection();
1059   auto caller_first_transceiver = caller->AddTransceiver(first_type_);
1060   auto callee = CreatePeerConnection();
1061 
1062   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1063 
1064   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
1065   auto callee_first_transceiver = callee->pc()->GetTransceivers()[0];
1066   std::string first_mid = *callee_first_transceiver->mid();
1067   caller_first_transceiver->StopInternal();
1068 
1069   // The reoffer will have a rejected m= section.
1070   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1071 
1072   auto callee_second_transceiver = callee->AddTransceiver(second_type_);
1073 
1074   // The reoffer should not recycle the existing m= section since it is not
1075   // rejected in either the *current* local or *current* remote description.
1076   auto reoffer = callee->CreateOffer();
1077   auto reoffer_contents = reoffer->description()->contents();
1078   ASSERT_EQ(2u, reoffer_contents.size());
1079   EXPECT_TRUE(reoffer_contents[0].rejected);
1080   EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type());
1081   EXPECT_EQ(first_mid, reoffer_contents[0].name);
1082   EXPECT_FALSE(reoffer_contents[1].rejected);
1083   EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type());
1084   std::string second_mid = reoffer_contents[1].name;
1085   EXPECT_NE(first_mid, second_mid);
1086 
1087   // Note: Cannot actually set the reoffer since the callee is in the signaling
1088   // state 'have-remote-offer'.
1089 }
1090 
1091 // Test that an m= section is *not* recycled if the media section is only
1092 // rejected in the pending remote description and not rejected in the current
1093 // local description.
TEST_P(RecycleMediaSectionTest,PendingRemoteRejectedAndNotRejectedLocal)1094 TEST_P(RecycleMediaSectionTest, PendingRemoteRejectedAndNotRejectedLocal) {
1095   auto caller = CreatePeerConnection();
1096   auto caller_first_transceiver = caller->AddTransceiver(first_type_);
1097   auto callee = CreatePeerConnection();
1098 
1099   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1100 
1101   ASSERT_EQ(1u, callee->pc()->GetTransceivers().size());
1102   auto callee_first_transceiver = callee->pc()->GetTransceivers()[0];
1103   std::string first_mid = *callee_first_transceiver->mid();
1104   caller_first_transceiver->StopInternal();
1105 
1106   // The reoffer will have a rejected m= section.
1107   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1108 
1109   auto callee_second_transceiver = callee->AddTransceiver(second_type_);
1110 
1111   // The reoffer should not recycle the existing m= section since it is not
1112   // rejected in either the *current* local or *current* remote description.
1113   auto reoffer = callee->CreateOffer();
1114   auto reoffer_contents = reoffer->description()->contents();
1115   ASSERT_EQ(2u, reoffer_contents.size());
1116   EXPECT_TRUE(reoffer_contents[0].rejected);
1117   EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type());
1118   EXPECT_EQ(first_mid, reoffer_contents[0].name);
1119   EXPECT_FALSE(reoffer_contents[1].rejected);
1120   EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type());
1121   std::string second_mid = reoffer_contents[1].name;
1122   EXPECT_NE(first_mid, second_mid);
1123 
1124   // Note: Cannot actually set the reoffer since the callee is in the signaling
1125   // state 'have-remote-offer'.
1126 }
1127 
1128 // Test all combinations of audio and video as the first and second media type
1129 // for the media section. This is needed for full test coverage because
1130 // MediaSession has separate functions for processing audio and video media
1131 // sections.
1132 INSTANTIATE_TEST_SUITE_P(
1133     PeerConnectionJsepTest,
1134     RecycleMediaSectionTest,
1135     Combine(Values(cricket::MEDIA_TYPE_AUDIO, cricket::MEDIA_TYPE_VIDEO),
1136             Values(cricket::MEDIA_TYPE_AUDIO, cricket::MEDIA_TYPE_VIDEO)));
1137 
1138 // Test that a new data channel section will not reuse a recycleable audio or
1139 // video media section. Additionally, tests that the new section is added to the
1140 // end of the session description.
TEST_F(PeerConnectionJsepTest,DataChannelDoesNotRecycleMediaSection)1141 TEST_F(PeerConnectionJsepTest, DataChannelDoesNotRecycleMediaSection) {
1142   auto caller = CreatePeerConnection();
1143   auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1144   auto callee = CreatePeerConnection();
1145 
1146   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1147 
1148   transceiver->StopInternal();
1149 
1150   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1151 
1152   caller->CreateDataChannel("dc");
1153 
1154   auto offer = caller->CreateOffer();
1155   auto offer_contents = offer->description()->contents();
1156   ASSERT_EQ(2u, offer_contents.size());
1157   EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO,
1158             offer_contents[0].media_description()->type());
1159   EXPECT_EQ(cricket::MEDIA_TYPE_DATA,
1160             offer_contents[1].media_description()->type());
1161 
1162   ASSERT_TRUE(
1163       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1164   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1165 
1166   auto answer = callee->CreateAnswer();
1167   auto answer_contents = answer->description()->contents();
1168   ASSERT_EQ(2u, answer_contents.size());
1169   EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO,
1170             answer_contents[0].media_description()->type());
1171   EXPECT_EQ(cricket::MEDIA_TYPE_DATA,
1172             answer_contents[1].media_description()->type());
1173 }
1174 
1175 // Test that if a new track is added to an existing session that has a data,
1176 // the new section comes at the end of the new offer, after the existing data
1177 // section.
TEST_F(PeerConnectionJsepTest,AudioTrackAddedAfterDataSectionInReoffer)1178 TEST_F(PeerConnectionJsepTest, AudioTrackAddedAfterDataSectionInReoffer) {
1179   auto caller = CreatePeerConnection();
1180   caller->CreateDataChannel("dc");
1181   auto callee = CreatePeerConnection();
1182 
1183   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1184 
1185   caller->AddAudioTrack("a");
1186 
1187   auto offer = caller->CreateOffer();
1188   auto contents = offer->description()->contents();
1189   ASSERT_EQ(2u, contents.size());
1190   EXPECT_EQ(cricket::MEDIA_TYPE_DATA, contents[0].media_description()->type());
1191   EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, contents[1].media_description()->type());
1192 }
1193 
1194 // Tests for MID properties.
1195 
RenameSection(size_t mline_index,const std::string & new_mid,SessionDescriptionInterface * sdesc)1196 static void RenameSection(size_t mline_index,
1197                           const std::string& new_mid,
1198                           SessionDescriptionInterface* sdesc) {
1199   cricket::SessionDescription* desc = sdesc->description();
1200   std::string old_mid = desc->contents()[mline_index].name;
1201   desc->contents()[mline_index].name = new_mid;
1202   desc->transport_infos()[mline_index].content_name = new_mid;
1203   const cricket::ContentGroup* bundle =
1204       desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
1205   if (bundle) {
1206     cricket::ContentGroup new_bundle = *bundle;
1207     if (new_bundle.RemoveContentName(old_mid)) {
1208       new_bundle.AddContentName(new_mid);
1209     }
1210     desc->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1211     desc->AddGroup(new_bundle);
1212   }
1213 }
1214 
1215 // Test that two PeerConnections can have a successful offer/answer exchange if
1216 // the MIDs are changed from the defaults.
TEST_F(PeerConnectionJsepTest,OfferAnswerWithChangedMids)1217 TEST_F(PeerConnectionJsepTest, OfferAnswerWithChangedMids) {
1218   constexpr char kFirstMid[] = "nondefaultmid";
1219   constexpr char kSecondMid[] = "randommid";
1220 
1221   auto caller = CreatePeerConnection();
1222   caller->AddAudioTrack("a");
1223   caller->AddAudioTrack("b");
1224   auto callee = CreatePeerConnection();
1225 
1226   auto offer = caller->CreateOffer();
1227   RenameSection(0, kFirstMid, offer.get());
1228   RenameSection(1, kSecondMid, offer.get());
1229 
1230   ASSERT_TRUE(
1231       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1232   auto caller_transceivers = caller->pc()->GetTransceivers();
1233   EXPECT_EQ(kFirstMid, caller_transceivers[0]->mid());
1234   EXPECT_EQ(kSecondMid, caller_transceivers[1]->mid());
1235 
1236   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1237   auto callee_transceivers = callee->pc()->GetTransceivers();
1238   EXPECT_EQ(kFirstMid, callee_transceivers[0]->mid());
1239   EXPECT_EQ(kSecondMid, callee_transceivers[1]->mid());
1240 
1241   auto answer = callee->CreateAnswer();
1242   auto answer_contents = answer->description()->contents();
1243   EXPECT_EQ(kFirstMid, answer_contents[0].name);
1244   EXPECT_EQ(kSecondMid, answer_contents[1].name);
1245 
1246   ASSERT_TRUE(
1247       callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1248   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1249 }
1250 
1251 // Test that CreateOffer will generate a MID that is not already used if the
1252 // default it would have picked is already taken. This is tested by using a
1253 // third PeerConnection to determine what the default would be for the second
1254 // media section then setting that as the first media section's MID.
TEST_F(PeerConnectionJsepTest,CreateOfferGeneratesUniqueMidIfAlreadyTaken)1255 TEST_F(PeerConnectionJsepTest, CreateOfferGeneratesUniqueMidIfAlreadyTaken) {
1256   // First, find what the default MID is for the second media section.
1257   auto pc = CreatePeerConnection();
1258   pc->AddAudioTrack("a");
1259   pc->AddAudioTrack("b");
1260   auto default_offer = pc->CreateOffer();
1261   std::string default_second_mid =
1262       default_offer->description()->contents()[1].name;
1263 
1264   // Now, do an offer/answer with one track which has the MID set to the default
1265   // second MID.
1266   auto caller = CreatePeerConnection();
1267   caller->AddAudioTrack("a");
1268   auto callee = CreatePeerConnection();
1269 
1270   auto offer = caller->CreateOffer();
1271   RenameSection(0, default_second_mid, offer.get());
1272 
1273   ASSERT_TRUE(
1274       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1275   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1276   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1277 
1278   // Add a second track and ensure that the MID is different.
1279   caller->AddAudioTrack("b");
1280 
1281   auto reoffer = caller->CreateOffer();
1282   auto reoffer_contents = reoffer->description()->contents();
1283   EXPECT_EQ(default_second_mid, reoffer_contents[0].name);
1284   EXPECT_NE(reoffer_contents[0].name, reoffer_contents[1].name);
1285 }
1286 
1287 // Test that if an audio or video section has the default data section MID, then
1288 // CreateOffer will generate a unique MID for the newly added data section.
TEST_F(PeerConnectionJsepTest,CreateOfferGeneratesUniqueMidForDataSectionIfAlreadyTaken)1289 TEST_F(PeerConnectionJsepTest,
1290        CreateOfferGeneratesUniqueMidForDataSectionIfAlreadyTaken) {
1291   // First, find what the default MID is for the data channel.
1292   auto pc = CreatePeerConnection();
1293   pc->CreateDataChannel("dc");
1294   auto default_offer = pc->CreateOffer();
1295   std::string default_data_mid =
1296       default_offer->description()->contents()[0].name;
1297 
1298   // Now do an offer/answer with one audio track which has a MID set to the
1299   // default data MID.
1300   auto caller = CreatePeerConnection();
1301   caller->AddAudioTrack("a");
1302   auto callee = CreatePeerConnection();
1303 
1304   auto offer = caller->CreateOffer();
1305   RenameSection(0, default_data_mid, offer.get());
1306 
1307   ASSERT_TRUE(
1308       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1309   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1310   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1311 
1312   // Add a data channel and ensure that the MID is different.
1313   caller->CreateDataChannel("dc");
1314 
1315   auto reoffer = caller->CreateOffer();
1316   auto reoffer_contents = reoffer->description()->contents();
1317   EXPECT_EQ(default_data_mid, reoffer_contents[0].name);
1318   EXPECT_NE(reoffer_contents[0].name, reoffer_contents[1].name);
1319 }
1320 
1321 // Test that a reoffer initiated by the callee adds a new track to the caller.
TEST_F(PeerConnectionJsepTest,CalleeDoesReoffer)1322 TEST_F(PeerConnectionJsepTest, CalleeDoesReoffer) {
1323   auto caller = CreatePeerConnection();
1324   caller->AddAudioTrack("a");
1325   auto callee = CreatePeerConnection();
1326   callee->AddAudioTrack("a");
1327   callee->AddVideoTrack("v");
1328 
1329   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1330 
1331   EXPECT_EQ(1u, caller->pc()->GetTransceivers().size());
1332   EXPECT_EQ(2u, callee->pc()->GetTransceivers().size());
1333 
1334   ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
1335 
1336   EXPECT_EQ(2u, caller->pc()->GetTransceivers().size());
1337   EXPECT_EQ(2u, callee->pc()->GetTransceivers().size());
1338 }
1339 
1340 // Tests for MSID properties.
1341 
1342 // Test that adding a track with AddTrack results in an offer that signals the
1343 // track's ID.
TEST_F(PeerConnectionJsepTest,AddingTrackWithAddTrackSpecifiesTrackId)1344 TEST_F(PeerConnectionJsepTest, AddingTrackWithAddTrackSpecifiesTrackId) {
1345   const std::string kTrackId = "audio_track";
1346 
1347   auto caller = CreatePeerConnection();
1348   caller->AddAudioTrack(kTrackId);
1349 
1350   auto offer = caller->CreateOffer();
1351   auto contents = offer->description()->contents();
1352   ASSERT_EQ(1u, contents.size());
1353   auto streams = contents[0].media_description()->streams();
1354   ASSERT_EQ(1u, streams.size());
1355   EXPECT_EQ(kTrackId, streams[0].id);
1356 }
1357 
1358 // Test that adding a track by calling AddTransceiver then SetTrack results in
1359 // an offer that does not signal the track's ID and signals a random ID.
TEST_F(PeerConnectionJsepTest,AddingTrackWithAddTransceiverSpecifiesRandomTrackId)1360 TEST_F(PeerConnectionJsepTest,
1361        AddingTrackWithAddTransceiverSpecifiesRandomTrackId) {
1362   const std::string kTrackId = "audio_track";
1363 
1364   auto caller = CreatePeerConnection();
1365   auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1366   transceiver->sender()->SetTrack(caller->CreateAudioTrack(kTrackId).get());
1367 
1368   auto offer = caller->CreateOffer();
1369   auto contents = offer->description()->contents();
1370   ASSERT_EQ(1u, contents.size());
1371   auto streams = contents[0].media_description()->streams();
1372   ASSERT_EQ(1u, streams.size());
1373   EXPECT_NE(kTrackId, streams[0].id);
1374 }
1375 
1376 // Test that if the transceiver is recvonly or inactive, then no MSID
1377 // information is included in the offer.
TEST_F(PeerConnectionJsepTest,NoMsidInOfferIfTransceiverDirectionHasNoSend)1378 TEST_F(PeerConnectionJsepTest, NoMsidInOfferIfTransceiverDirectionHasNoSend) {
1379   auto caller = CreatePeerConnection();
1380 
1381   RtpTransceiverInit init_recvonly;
1382   init_recvonly.direction = RtpTransceiverDirection::kRecvOnly;
1383   ASSERT_TRUE(caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init_recvonly));
1384 
1385   RtpTransceiverInit init_inactive;
1386   init_inactive.direction = RtpTransceiverDirection::kInactive;
1387   ASSERT_TRUE(caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init_inactive));
1388 
1389   auto offer = caller->CreateOffer();
1390   auto contents = offer->description()->contents();
1391   ASSERT_EQ(2u, contents.size());
1392   // MSID is specified in the first stream, so no streams means no MSID.
1393   EXPECT_EQ(0u, contents[0].media_description()->streams().size());
1394   EXPECT_EQ(0u, contents[1].media_description()->streams().size());
1395 }
1396 
1397 // Test that if an answer negotiates transceiver directions of recvonly or
1398 // inactive, then no MSID information is included in the answer.
TEST_F(PeerConnectionJsepTest,NoMsidInAnswerIfNoRespondingTracks)1399 TEST_F(PeerConnectionJsepTest, NoMsidInAnswerIfNoRespondingTracks) {
1400   auto caller = CreatePeerConnection();
1401   auto callee = CreatePeerConnection();
1402 
1403   // recvonly transceiver will get negotiated to inactive since the callee has
1404   // no tracks to send in response.
1405   RtpTransceiverInit init_recvonly;
1406   init_recvonly.direction = RtpTransceiverDirection::kRecvOnly;
1407   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init_recvonly);
1408 
1409   // sendrecv transceiver will get negotiated to recvonly since the callee has
1410   // no tracks to send in response.
1411   RtpTransceiverInit init_sendrecv;
1412   init_sendrecv.direction = RtpTransceiverDirection::kSendRecv;
1413   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init_sendrecv);
1414 
1415   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1416 
1417   auto answer = callee->CreateAnswer();
1418   auto contents = answer->description()->contents();
1419   ASSERT_EQ(2u, contents.size());
1420   // MSID is specified in the first stream, so no streams means no MSID.
1421   EXPECT_EQ(0u, contents[0].media_description()->streams().size());
1422   EXPECT_EQ(0u, contents[1].media_description()->streams().size());
1423 }
1424 
1425 // Test that the MSID is included even if the transceiver direction has changed
1426 // to inactive if the transceiver had previously sent media.
TEST_F(PeerConnectionJsepTest,IncludeMsidEvenIfDirectionHasChanged)1427 TEST_F(PeerConnectionJsepTest, IncludeMsidEvenIfDirectionHasChanged) {
1428   auto caller = CreatePeerConnection();
1429   caller->AddAudioTrack("audio");
1430   auto callee = CreatePeerConnection();
1431   callee->AddAudioTrack("audio");
1432 
1433   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1434 
1435   caller->pc()->GetTransceivers()[0]->SetDirectionWithError(
1436       RtpTransceiverDirection::kInactive);
1437 
1438   // The transceiver direction on both sides will turn to inactive.
1439   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1440 
1441   auto* offer = callee->pc()->remote_description();
1442   auto offer_contents = offer->description()->contents();
1443   ASSERT_EQ(1u, offer_contents.size());
1444   // MSID is specified in the first stream. If it is present, assume that MSID
1445   // is there.
1446   EXPECT_EQ(1u, offer_contents[0].media_description()->streams().size());
1447 
1448   auto* answer = caller->pc()->remote_description();
1449   auto answer_contents = answer->description()->contents();
1450   ASSERT_EQ(1u, answer_contents.size());
1451   EXPECT_EQ(1u, answer_contents[0].media_description()->streams().size());
1452 }
1453 
1454 // Test that stopping a RtpTransceiver will cause future offers to not include
1455 // any MSID information for that section.
TEST_F(PeerConnectionJsepTest,RemoveMsidIfTransceiverStopped)1456 TEST_F(PeerConnectionJsepTest, RemoveMsidIfTransceiverStopped) {
1457   auto caller = CreatePeerConnection();
1458   auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1459   auto callee = CreatePeerConnection();
1460 
1461   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1462 
1463   transceiver->StopInternal();
1464 
1465   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1466 
1467   auto* offer = callee->pc()->remote_description();
1468   auto offer_contents = offer->description()->contents();
1469   ASSERT_EQ(1u, offer_contents.size());
1470   // MSID is specified in the first stream, so no streams means no MSID.
1471   EXPECT_EQ(0u, offer_contents[0].media_description()->streams().size());
1472 }
1473 
1474 // Test that the callee RtpReceiver created by a call to SetRemoteDescription
1475 // has its ID set to the signaled track ID.
TEST_F(PeerConnectionJsepTest,RtpReceiverCreatedBySetRemoteDescriptionHasSignaledTrackId)1476 TEST_F(PeerConnectionJsepTest,
1477        RtpReceiverCreatedBySetRemoteDescriptionHasSignaledTrackId) {
1478   const std::string kTrackId = "audio_track";
1479 
1480   auto caller = CreatePeerConnection();
1481   auto callee = CreatePeerConnection();
1482   caller->AddAudioTrack(kTrackId);
1483 
1484   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1485 
1486   ASSERT_EQ(1u, callee->pc()->GetReceivers().size());
1487   auto receiver = callee->pc()->GetReceivers()[0];
1488   EXPECT_EQ(kTrackId, receiver->id());
1489 }
1490 
1491 // Test that if the callee RtpReceiver is reused by a call to
1492 // SetRemoteDescription, its ID does not change.
TEST_F(PeerConnectionJsepTest,RtpReceiverCreatedBeforeSetRemoteDescriptionKeepsId)1493 TEST_F(PeerConnectionJsepTest,
1494        RtpReceiverCreatedBeforeSetRemoteDescriptionKeepsId) {
1495   const std::string kTrackId = "audio_track";
1496 
1497   auto caller = CreatePeerConnection();
1498   auto callee = CreatePeerConnection();
1499   caller->AddAudioTrack(kTrackId);
1500   callee->AddAudioTrack("dummy_track");
1501 
1502   ASSERT_EQ(1u, callee->pc()->GetReceivers().size());
1503   auto receiver = callee->pc()->GetReceivers()[0];
1504   std::string receiver_id = receiver->id();
1505 
1506   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1507 
1508   EXPECT_EQ(receiver_id, receiver->id());
1509 }
1510 
1511 // Test that setting a remote offer with one track that has no streams fires off
1512 // the correct OnAddTrack event.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferWithOneTrackNoStreamFiresOnAddTrack)1513 TEST_F(PeerConnectionJsepTest,
1514        SetRemoteOfferWithOneTrackNoStreamFiresOnAddTrack) {
1515   const std::string kTrackLabel = "audio_track";
1516 
1517   auto caller = CreatePeerConnection();
1518   auto callee = CreatePeerConnection();
1519   ASSERT_TRUE(caller->AddAudioTrack(kTrackLabel));
1520 
1521   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1522 
1523   const auto& track_events = callee->observer()->add_track_events_;
1524   ASSERT_EQ(1u, track_events.size());
1525   const auto& event = track_events[0];
1526   EXPECT_EQ(kTrackLabel, event.receiver->track()->id());
1527   EXPECT_EQ(0u, event.streams.size());
1528 }
1529 
1530 // Test that setting a remote offer with one track that has one stream fires off
1531 // the correct OnAddTrack event.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferWithOneTrackOneStreamFiresOnAddTrack)1532 TEST_F(PeerConnectionJsepTest,
1533        SetRemoteOfferWithOneTrackOneStreamFiresOnAddTrack) {
1534   const std::string kTrackLabel = "audio_track";
1535   const std::string kStreamId = "audio_stream";
1536 
1537   auto caller = CreatePeerConnection();
1538   auto callee = CreatePeerConnection();
1539   ASSERT_TRUE(caller->AddAudioTrack(kTrackLabel, {kStreamId}));
1540 
1541   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1542 
1543   const auto& track_events = callee->observer()->add_track_events_;
1544   ASSERT_EQ(1u, track_events.size());
1545   const auto& event = track_events[0];
1546   ASSERT_EQ(1u, event.streams.size());
1547   auto stream = event.streams[0];
1548   EXPECT_EQ(kStreamId, stream->id());
1549   EXPECT_THAT(track_events[0].snapshotted_stream_tracks.at(stream),
1550               ElementsAre(event.receiver->track()));
1551   EXPECT_EQ(event.receiver->streams(), track_events[0].streams);
1552 }
1553 
1554 // Test that setting a remote offer with two tracks that share the same stream
1555 // fires off two OnAddTrack events, both with the same stream that has both
1556 // tracks present at the time of firing. This is to ensure that track events are
1557 // not fired until SetRemoteDescription has finished processing all the media
1558 // sections.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferWithTwoTracksSameStreamFiresOnAddTrack)1559 TEST_F(PeerConnectionJsepTest,
1560        SetRemoteOfferWithTwoTracksSameStreamFiresOnAddTrack) {
1561   const std::string kTrack1Label = "audio_track1";
1562   const std::string kTrack2Label = "audio_track2";
1563   const std::string kSharedStreamId = "stream";
1564 
1565   auto caller = CreatePeerConnection();
1566   auto callee = CreatePeerConnection();
1567   ASSERT_TRUE(caller->AddAudioTrack(kTrack1Label, {kSharedStreamId}));
1568   ASSERT_TRUE(caller->AddAudioTrack(kTrack2Label, {kSharedStreamId}));
1569 
1570   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1571 
1572   const auto& track_events = callee->observer()->add_track_events_;
1573   ASSERT_EQ(2u, track_events.size());
1574   const auto& event1 = track_events[0];
1575   const auto& event2 = track_events[1];
1576   ASSERT_EQ(1u, event1.streams.size());
1577   auto stream = event1.streams[0];
1578   ASSERT_THAT(event2.streams, ElementsAre(stream));
1579   auto track1 = event1.receiver->track();
1580   auto track2 = event2.receiver->track();
1581   EXPECT_THAT(event1.snapshotted_stream_tracks.at(stream),
1582               UnorderedElementsAre(track1, track2));
1583   EXPECT_THAT(event2.snapshotted_stream_tracks.at(stream),
1584               UnorderedElementsAre(track1, track2));
1585 }
1586 
1587 // Test that setting a remote offer with one track that has two streams fires
1588 // off the correct OnAddTrack event.
TEST_F(PeerConnectionJsepTest,SetRemoteOfferWithOneTrackTwoStreamFiresOnAddTrack)1589 TEST_F(PeerConnectionJsepTest,
1590        SetRemoteOfferWithOneTrackTwoStreamFiresOnAddTrack) {
1591   const std::string kTrackLabel = "audio_track";
1592   const std::string kStreamId1 = "audio_stream1";
1593   const std::string kStreamId2 = "audio_stream2";
1594 
1595   auto caller = CreatePeerConnection();
1596   auto callee = CreatePeerConnection();
1597   ASSERT_TRUE(caller->AddAudioTrack(kTrackLabel, {kStreamId1, kStreamId2}));
1598 
1599   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1600 
1601   const auto& track_events = callee->observer()->add_track_events_;
1602   ASSERT_EQ(1u, track_events.size());
1603   const auto& event = track_events[0];
1604   ASSERT_EQ(2u, event.streams.size());
1605   EXPECT_EQ(kStreamId1, event.streams[0]->id());
1606   EXPECT_EQ(kStreamId2, event.streams[1]->id());
1607 }
1608 
1609 // Test that if an RtpTransceiver with a current_direction set is stopped, then
1610 // current_direction is changed to null.
TEST_F(PeerConnectionJsepTest,CurrentDirectionResetWhenRtpTransceiverStopped)1611 TEST_F(PeerConnectionJsepTest, CurrentDirectionResetWhenRtpTransceiverStopped) {
1612   auto caller = CreatePeerConnection();
1613   auto callee = CreatePeerConnection();
1614 
1615   auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1616 
1617   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1618 
1619   ASSERT_TRUE(transceiver->current_direction());
1620   transceiver->StopInternal();
1621   EXPECT_EQ(transceiver->current_direction(),
1622             RtpTransceiverDirection::kStopped);
1623 }
1624 
1625 // Test that you can't set an answer on a PeerConnection before setting the
1626 // offer.
TEST_F(PeerConnectionJsepTest,AnswerBeforeOfferFails)1627 TEST_F(PeerConnectionJsepTest, AnswerBeforeOfferFails) {
1628   auto caller = CreatePeerConnection();
1629   auto callee = CreatePeerConnection();
1630   caller->AddAudioTrack("audio");
1631 
1632   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1633 
1634   RTCError error;
1635   ASSERT_FALSE(caller->SetRemoteDescription(callee->CreateAnswer(), &error));
1636   EXPECT_EQ(RTCErrorType::INVALID_STATE, error.type());
1637 }
1638 
1639 // Test that a Unified Plan PeerConnection fails to set a Plan B offer if it has
1640 // two video tracks.
TEST_F(PeerConnectionJsepTest,TwoVideoPlanBToUnifiedPlanFails)1641 TEST_F(PeerConnectionJsepTest, TwoVideoPlanBToUnifiedPlanFails) {
1642   RTCConfiguration config_planb;
1643   config_planb.sdp_semantics = SdpSemantics::kPlanB_DEPRECATED;
1644   auto caller = CreatePeerConnection(config_planb);
1645   auto callee = CreatePeerConnection();
1646   caller->AddVideoTrack("video1");
1647   caller->AddVideoTrack("video2");
1648 
1649   RTCError error;
1650   ASSERT_FALSE(callee->SetRemoteDescription(caller->CreateOffer(), &error));
1651   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, error.type());
1652 }
1653 
1654 // Test that a Unified Plan PeerConnection fails to set a Plan B answer if it
1655 // has two video tracks.
TEST_F(PeerConnectionJsepTest,OneVideoUnifiedPlanToTwoVideoPlanBFails)1656 TEST_F(PeerConnectionJsepTest, OneVideoUnifiedPlanToTwoVideoPlanBFails) {
1657   auto caller = CreatePeerConnection();
1658   RTCConfiguration config_planb;
1659   config_planb.sdp_semantics = SdpSemantics::kPlanB_DEPRECATED;
1660   auto callee = CreatePeerConnection(config_planb);
1661   caller->AddVideoTrack("video");
1662   callee->AddVideoTrack("video1");
1663   callee->AddVideoTrack("video2");
1664 
1665   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1666 
1667   RTCError error;
1668   ASSERT_FALSE(caller->SetRemoteDescription(caller->CreateAnswer(), &error));
1669   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, error.type());
1670 }
1671 
1672 // Removes the RTP header extension associated with the given URI from the media
1673 // description.
RemoveRtpHeaderExtensionByUri(MediaContentDescription * media_description,absl::string_view uri)1674 static void RemoveRtpHeaderExtensionByUri(
1675     MediaContentDescription* media_description,
1676     absl::string_view uri) {
1677   std::vector<RtpExtension> header_extensions =
1678       media_description->rtp_header_extensions();
1679   header_extensions.erase(std::remove_if(
1680       header_extensions.begin(), header_extensions.end(),
1681       [uri](const RtpExtension& extension) { return extension.uri == uri; }));
1682   media_description->set_rtp_header_extensions(header_extensions);
1683 }
1684 
1685 // Transforms a session description to emulate a legacy endpoint which does not
1686 // support a=mid, BUNDLE, and the MID header extension.
ClearMids(SessionDescriptionInterface * sdesc)1687 static void ClearMids(SessionDescriptionInterface* sdesc) {
1688   cricket::SessionDescription* desc = sdesc->description();
1689   desc->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1690   cricket::ContentInfo* audio_content = cricket::GetFirstAudioContent(desc);
1691   if (audio_content) {
1692     desc->GetTransportInfoByName(audio_content->name)->content_name = "";
1693     audio_content->name = "";
1694     RemoveRtpHeaderExtensionByUri(audio_content->media_description(),
1695                                   RtpExtension::kMidUri);
1696   }
1697   cricket::ContentInfo* video_content = cricket::GetFirstVideoContent(desc);
1698   if (video_content) {
1699     desc->GetTransportInfoByName(video_content->name)->content_name = "";
1700     video_content->name = "";
1701     RemoveRtpHeaderExtensionByUri(video_content->media_description(),
1702                                   RtpExtension::kMidUri);
1703   }
1704 }
1705 
1706 // Test that negotiation works with legacy endpoints which do not support a=mid.
TEST_F(PeerConnectionJsepTest,LegacyNoMidAudioOnlyOffer)1707 TEST_F(PeerConnectionJsepTest, LegacyNoMidAudioOnlyOffer) {
1708   auto caller = CreatePeerConnection();
1709   caller->AddAudioTrack("audio");
1710   auto callee = CreatePeerConnection();
1711   callee->AddAudioTrack("audio");
1712 
1713   auto offer = caller->CreateOffer();
1714   ClearMids(offer.get());
1715 
1716   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1717   EXPECT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
1718 }
TEST_F(PeerConnectionJsepTest,LegacyNoMidAudioVideoOffer)1719 TEST_F(PeerConnectionJsepTest, LegacyNoMidAudioVideoOffer) {
1720   auto caller = CreatePeerConnection();
1721   caller->AddAudioTrack("audio");
1722   caller->AddVideoTrack("video");
1723   auto callee = CreatePeerConnection();
1724   callee->AddAudioTrack("audio");
1725   callee->AddVideoTrack("video");
1726 
1727   auto offer = caller->CreateOffer();
1728   ClearMids(offer.get());
1729 
1730   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1731   EXPECT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
1732 }
TEST_F(PeerConnectionJsepTest,LegacyNoMidAudioOnlyAnswer)1733 TEST_F(PeerConnectionJsepTest, LegacyNoMidAudioOnlyAnswer) {
1734   auto caller = CreatePeerConnection();
1735   caller->AddAudioTrack("audio");
1736   auto callee = CreatePeerConnection();
1737   callee->AddAudioTrack("audio");
1738 
1739   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1740 
1741   auto answer = callee->CreateAnswer();
1742   ClearMids(answer.get());
1743 
1744   EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1745 }
TEST_F(PeerConnectionJsepTest,LegacyNoMidAudioVideoAnswer)1746 TEST_F(PeerConnectionJsepTest, LegacyNoMidAudioVideoAnswer) {
1747   auto caller = CreatePeerConnection();
1748   caller->AddAudioTrack("audio");
1749   caller->AddVideoTrack("video");
1750   auto callee = CreatePeerConnection();
1751   callee->AddAudioTrack("audio");
1752   callee->AddVideoTrack("video");
1753 
1754   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1755 
1756   auto answer = callee->CreateAnswer();
1757   ClearMids(answer.get());
1758 
1759   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1760 }
1761 
1762 // Test that negotiation works with legacy endpoints which do not support a=mid
1763 // when setting two remote descriptions without setting a local description in
1764 // between.
TEST_F(PeerConnectionJsepTest,LegacyNoMidTwoRemoteOffers)1765 TEST_F(PeerConnectionJsepTest, LegacyNoMidTwoRemoteOffers) {
1766   auto caller = CreatePeerConnection();
1767   caller->AddAudioTrack("audio");
1768   auto callee = CreatePeerConnection();
1769   callee->AddAudioTrack("audio");
1770 
1771   auto offer = caller->CreateOffer();
1772   ClearMids(offer.get());
1773 
1774   ASSERT_TRUE(
1775       callee->SetRemoteDescription(CloneSessionDescription(offer.get())));
1776   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1777   EXPECT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
1778 }
1779 
1780 // Test that SetLocalDescription fails if a=mid lines are missing.
TEST_F(PeerConnectionJsepTest,SetLocalDescriptionFailsMissingMid)1781 TEST_F(PeerConnectionJsepTest, SetLocalDescriptionFailsMissingMid) {
1782   auto caller = CreatePeerConnection();
1783   caller->AddAudioTrack("audio");
1784 
1785   auto offer = caller->CreateOffer();
1786   ClearMids(offer.get());
1787 
1788   std::string error;
1789   ASSERT_FALSE(caller->SetLocalDescription(std::move(offer), &error));
1790   EXPECT_EQ(
1791       "Failed to set local offer sdp: A media section is missing a MID "
1792       "attribute.",
1793       error);
1794 }
1795 
TEST_F(PeerConnectionJsepTest,RollbackSupportedInUnifiedPlan)1796 TEST_F(PeerConnectionJsepTest, RollbackSupportedInUnifiedPlan) {
1797   RTCConfiguration config;
1798   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1799   config.enable_implicit_rollback = true;
1800   auto caller = CreatePeerConnection(config);
1801   auto callee = CreatePeerConnection(config);
1802   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
1803   EXPECT_TRUE(caller->SetLocalDescription(caller->CreateRollback()));
1804   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
1805   EXPECT_TRUE(caller->SetRemoteDescription(caller->CreateRollback()));
1806   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
1807   EXPECT_TRUE(caller->SetRemoteDescription(callee->CreateOffer()));
1808 }
1809 
TEST_F(PeerConnectionJsepTest,RollbackNotSupportedInPlanB)1810 TEST_F(PeerConnectionJsepTest, RollbackNotSupportedInPlanB) {
1811   RTCConfiguration config;
1812   config.sdp_semantics = SdpSemantics::kPlanB_DEPRECATED;
1813   config.enable_implicit_rollback = true;
1814   auto caller = CreatePeerConnection(config);
1815   auto callee = CreatePeerConnection(config);
1816   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
1817   EXPECT_FALSE(caller->SetLocalDescription(caller->CreateRollback()));
1818   EXPECT_FALSE(caller->SetRemoteDescription(caller->CreateRollback()));
1819   EXPECT_FALSE(caller->SetRemoteDescription(callee->CreateOffer()));
1820 }
1821 
TEST_F(PeerConnectionJsepTest,RollbackFailsInStableState)1822 TEST_F(PeerConnectionJsepTest, RollbackFailsInStableState) {
1823   auto caller = CreatePeerConnection();
1824   EXPECT_FALSE(caller->SetLocalDescription(caller->CreateRollback()));
1825   EXPECT_FALSE(caller->SetRemoteDescription(caller->CreateRollback()));
1826 }
1827 
TEST_F(PeerConnectionJsepTest,RollbackToStableStateAndClearLocalOffer)1828 TEST_F(PeerConnectionJsepTest, RollbackToStableStateAndClearLocalOffer) {
1829   auto caller = CreatePeerConnection();
1830   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
1831   EXPECT_TRUE(caller->SetLocalDescription(caller->CreateRollback()));
1832   EXPECT_EQ(caller->signaling_state(), PeerConnectionInterface::kStable);
1833   EXPECT_EQ(caller->pc()->pending_local_description(), nullptr);
1834 
1835   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
1836   EXPECT_TRUE(caller->SetRemoteDescription(caller->CreateRollback()));
1837   EXPECT_EQ(caller->signaling_state(), PeerConnectionInterface::kStable);
1838   EXPECT_EQ(caller->pc()->pending_local_description(), nullptr);
1839 }
1840 
TEST_F(PeerConnectionJsepTest,RollbackToStableStateAndClearRemoteOffer)1841 TEST_F(PeerConnectionJsepTest, RollbackToStableStateAndClearRemoteOffer) {
1842   auto caller = CreatePeerConnection();
1843   auto callee = CreatePeerConnection();
1844   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1845   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
1846   EXPECT_EQ(callee->signaling_state(), PeerConnectionInterface::kStable);
1847   EXPECT_EQ(callee->pc()->pending_remote_description(), nullptr);
1848 
1849   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1850   EXPECT_TRUE(callee->SetLocalDescription(caller->CreateRollback()));
1851   EXPECT_EQ(callee->signaling_state(), PeerConnectionInterface::kStable);
1852   EXPECT_EQ(callee->pc()->pending_remote_description(), nullptr);
1853 }
1854 
TEST_F(PeerConnectionJsepTest,RollbackImplicitly)1855 TEST_F(PeerConnectionJsepTest, RollbackImplicitly) {
1856   RTCConfiguration config;
1857   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1858   config.enable_implicit_rollback = true;
1859   auto caller = CreatePeerConnection(config);
1860   auto callee = CreatePeerConnection(config);
1861   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
1862   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1863   EXPECT_EQ(callee->signaling_state(),
1864             PeerConnectionInterface::kHaveRemoteOffer);
1865   EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal());
1866   EXPECT_FALSE(callee->observer()->legacy_renegotiation_needed());
1867   EXPECT_FALSE(callee->observer()->has_negotiation_needed_event());
1868 }
1869 
TEST_F(PeerConnectionJsepTest,RollbackImplicitlyNegotatiationNotNeeded)1870 TEST_F(PeerConnectionJsepTest, RollbackImplicitlyNegotatiationNotNeeded) {
1871   RTCConfiguration config;
1872   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1873   config.enable_implicit_rollback = true;
1874   auto caller = CreatePeerConnection(config);
1875   auto callee = CreatePeerConnection(config);
1876   caller->AddAudioTrack("a");
1877   callee->AddAudioTrack("b");
1878   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
1879   callee->observer()->clear_legacy_renegotiation_needed();
1880   callee->observer()->clear_latest_negotiation_needed_event();
1881   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1882   EXPECT_EQ(callee->signaling_state(),
1883             PeerConnectionInterface::kHaveRemoteOffer);
1884   EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal());
1885   // No negotiation needed as track got attached in the answer.
1886   EXPECT_FALSE(callee->observer()->legacy_renegotiation_needed());
1887   EXPECT_FALSE(callee->observer()->has_negotiation_needed_event());
1888   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 0u);
1889 }
1890 
TEST_F(PeerConnectionJsepTest,RollbackImplicitlyAndNegotiationNeeded)1891 TEST_F(PeerConnectionJsepTest, RollbackImplicitlyAndNegotiationNeeded) {
1892   RTCConfiguration config;
1893   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1894   config.enable_implicit_rollback = true;
1895   auto caller = CreatePeerConnection(config);
1896   auto callee = CreatePeerConnection(config);
1897   callee->AddAudioTrack("a");
1898   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
1899   callee->observer()->clear_legacy_renegotiation_needed();
1900   callee->observer()->clear_latest_negotiation_needed_event();
1901   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1902   EXPECT_EQ(callee->signaling_state(),
1903             PeerConnectionInterface::kHaveRemoteOffer);
1904   EXPECT_FALSE(callee->observer()->legacy_renegotiation_needed());
1905   EXPECT_FALSE(callee->observer()->has_negotiation_needed_event());
1906   EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal());
1907   EXPECT_TRUE(callee->observer()->legacy_renegotiation_needed());
1908   EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
1909   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 0u);
1910 }
1911 
TEST_F(PeerConnectionJsepTest,AttemptToRollbackImplicitly)1912 TEST_F(PeerConnectionJsepTest, AttemptToRollbackImplicitly) {
1913   RTCConfiguration config;
1914   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1915   config.enable_implicit_rollback = true;
1916   auto caller = CreatePeerConnection(config);
1917   auto callee = CreatePeerConnection(config);
1918   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
1919   EXPECT_FALSE(callee->SetRemoteDescription(
1920       CreateSessionDescription(SdpType::kOffer, "invalid sdp")));
1921   EXPECT_EQ(callee->signaling_state(),
1922             PeerConnectionInterface::kHaveLocalOffer);
1923 }
1924 
TEST_F(PeerConnectionJsepTest,RollbackRemovesTransceiver)1925 TEST_F(PeerConnectionJsepTest, RollbackRemovesTransceiver) {
1926   auto caller = CreatePeerConnection();
1927   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1928   auto callee = CreatePeerConnection();
1929   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1930   ASSERT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1931   auto transceiver = callee->pc()->GetTransceivers()[0];
1932   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
1933   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 0u);
1934   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 1u);
1935   // The removed transceiver should be stopped and its receiver track should be
1936   // ended.
1937   EXPECT_TRUE(transceiver->stopping());
1938   EXPECT_TRUE(transceiver->stopping());
1939   EXPECT_EQ(transceiver->receiver()->track()->state(),
1940             MediaStreamTrackInterface::kEnded);
1941 }
1942 
TEST_F(PeerConnectionJsepTest,RollbackKeepsTransceiverAndClearsMid)1943 TEST_F(PeerConnectionJsepTest, RollbackKeepsTransceiverAndClearsMid) {
1944   auto caller = CreatePeerConnection();
1945   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1946   auto callee = CreatePeerConnection();
1947   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1948   callee->AddAudioTrack("a");
1949   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1950   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
1951   // Transceiver can't be removed as track was added to it.
1952   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1953   // Mid got cleared to make it reusable.
1954   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->mid(), absl::nullopt);
1955   // Transceiver should be counted as addTrack-created after rollback.
1956   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1957   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1958   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 1u);
1959   // Because the transceiver is reusable, it must not be stopped and its
1960   // receiver track must still be live.
1961   auto transceiver = callee->pc()->GetTransceivers()[0];
1962   EXPECT_FALSE(transceiver->stopping());
1963   EXPECT_FALSE(transceiver->stopping());
1964   EXPECT_EQ(transceiver->receiver()->track()->state(),
1965             MediaStreamTrackInterface::kLive);
1966 }
1967 
TEST_F(PeerConnectionJsepTest,RollbackKeepsTransceiverAfterAddTrackEvenWhenTrackIsNulled)1968 TEST_F(PeerConnectionJsepTest,
1969        RollbackKeepsTransceiverAfterAddTrackEvenWhenTrackIsNulled) {
1970   auto caller = CreatePeerConnection();
1971   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1972   auto callee = CreatePeerConnection();
1973   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1974   callee->AddAudioTrack("a");
1975   callee->pc()->GetTransceivers()[0]->sender()->SetTrack(nullptr);
1976   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->sender()->track(), nullptr);
1977   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1978   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
1979   // Transceiver can't be removed as track was added to it.
1980   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1981   // Mid got cleared to make it reusable.
1982   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->mid(), absl::nullopt);
1983   // Transceiver should be counted as addTrack-created after rollback.
1984   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1985   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1986   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 1u);
1987 }
1988 
TEST_F(PeerConnectionJsepTest,RollbackRestoresMid)1989 TEST_F(PeerConnectionJsepTest, RollbackRestoresMid) {
1990   auto caller = CreatePeerConnection();
1991   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1992   auto callee = CreatePeerConnection();
1993   callee->AddAudioTrack("a");
1994   auto offer = callee->CreateOffer();
1995   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1996   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
1997   EXPECT_NE(callee->pc()->GetTransceivers()[0]->mid(), absl::nullopt);
1998   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
1999   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->mid(), absl::nullopt);
2000   EXPECT_TRUE(callee->SetLocalDescription(std::move(offer)));
2001 }
2002 
TEST_F(PeerConnectionJsepTest,RollbackRestoresInitSendEncodings)2003 TEST_F(PeerConnectionJsepTest, RollbackRestoresInitSendEncodings) {
2004   auto caller = CreatePeerConnection();
2005   RtpTransceiverInit init;
2006   init.direction = RtpTransceiverDirection::kSendRecv;
2007   RtpEncodingParameters encoding;
2008   encoding.rid = "hi";
2009   init.send_encodings.push_back(encoding);
2010   encoding.rid = "mid";
2011   init.send_encodings.push_back(encoding);
2012   encoding.rid = "lo";
2013   init.send_encodings.push_back(encoding);
2014   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
2015   auto encodings =
2016       caller->pc()->GetTransceivers()[0]->sender()->init_send_encodings();
2017   EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
2018   EXPECT_NE(caller->pc()->GetTransceivers()[0]->sender()->init_send_encodings(),
2019             encodings);
2020   EXPECT_TRUE(caller->SetLocalDescription(caller->CreateRollback()));
2021   EXPECT_EQ(caller->pc()->GetTransceivers()[0]->sender()->init_send_encodings(),
2022             encodings);
2023 }
2024 
TEST_F(PeerConnectionJsepTest,RollbackDoesNotAffectSendEncodings)2025 TEST_F(PeerConnectionJsepTest, RollbackDoesNotAffectSendEncodings) {
2026   auto caller = CreatePeerConnection();
2027   auto callee = CreatePeerConnection();
2028   RtpTransceiverInit init;
2029   init.direction = RtpTransceiverDirection::kSendOnly;
2030   RtpEncodingParameters encoding;
2031   encoding.rid = "hi";
2032   init.send_encodings.push_back(encoding);
2033   encoding.rid = "mid";
2034   init.send_encodings.push_back(encoding);
2035   encoding.rid = "lo";
2036   init.send_encodings.push_back(encoding);
2037   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
2038   callee->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2039   callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
2040   caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal());
2041   auto params = caller->pc()->GetTransceivers()[0]->sender()->GetParameters();
2042   EXPECT_TRUE(params.encodings[0].active);
2043   params.encodings[0].active = false;
2044   caller->pc()->GetTransceivers()[0]->sender()->SetParameters(params);
2045   auto offer = caller->CreateOffer();
2046   std::string offer_string;
2047   EXPECT_TRUE(offer.get()->ToString(&offer_string));
2048   std::string simulcast_line =
2049       offer_string.substr(offer_string.find("a=simulcast"));
2050   EXPECT_FALSE(simulcast_line.empty());
2051   EXPECT_TRUE(caller->SetLocalDescription(std::move(offer)));
2052   EXPECT_TRUE(caller->SetLocalDescription(caller->CreateRollback()));
2053   EXPECT_FALSE(caller->pc()
2054                    ->GetTransceivers()[0]
2055                    ->sender()
2056                    ->GetParameters()
2057                    .encodings[0]
2058                    .active);
2059   offer = caller->CreateOffer();
2060   EXPECT_TRUE(offer.get()->ToString(&offer_string));
2061   EXPECT_EQ(offer_string.substr(offer_string.find("a=simulcast")),
2062             simulcast_line);
2063 }
2064 
TEST_F(PeerConnectionJsepTest,RollbackRestoresMidAndRemovesTransceiver)2065 TEST_F(PeerConnectionJsepTest, RollbackRestoresMidAndRemovesTransceiver) {
2066   auto callee = CreatePeerConnection();
2067   callee->AddVideoTrack("a");
2068   auto offer = callee->CreateOffer();
2069   auto caller = CreatePeerConnection();
2070   caller->AddAudioTrack("b");
2071   caller->AddVideoTrack("c");
2072   auto mid = callee->pc()->GetTransceivers()[0]->mid();
2073   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2074   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 2u);
2075   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
2076   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2077   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->mid(), mid);
2078   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->media_type(),
2079             cricket::MEDIA_TYPE_VIDEO);
2080   EXPECT_TRUE(callee->SetLocalDescription(std::move(offer)));
2081   EXPECT_EQ(callee->observer()->remove_track_events_.size(),
2082             callee->observer()->add_track_events_.size());
2083 }
2084 
TEST_F(PeerConnectionJsepTest,RollbackHasNoEffectOnStableTransceivers)2085 TEST_F(PeerConnectionJsepTest, RollbackHasNoEffectOnStableTransceivers) {
2086   auto callee = CreatePeerConnection();
2087   callee->AddVideoTrack("a");
2088   auto caller = CreatePeerConnection();
2089   caller->AddAudioTrack("b");
2090   caller->AddVideoTrack("c");
2091   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2092   EXPECT_TRUE(
2093       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
2094   // In stable don't add or remove anything.
2095   callee->observer()->clear_legacy_renegotiation_needed();
2096   callee->observer()->clear_latest_negotiation_needed_event();
2097   size_t transceiver_count = callee->pc()->GetTransceivers().size();
2098   auto mid_0 = callee->pc()->GetTransceivers()[0]->mid();
2099   auto mid_1 = callee->pc()->GetTransceivers()[1]->mid();
2100   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2101   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
2102   EXPECT_EQ(callee->pc()->GetTransceivers().size(), transceiver_count);
2103   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->mid(), mid_0);
2104   EXPECT_EQ(callee->pc()->GetTransceivers()[1]->mid(), mid_1);
2105   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 0u);
2106   EXPECT_FALSE(callee->observer()->legacy_renegotiation_needed());
2107   EXPECT_FALSE(callee->observer()->has_negotiation_needed_event());
2108 }
2109 
TEST_F(PeerConnectionJsepTest,ImplicitlyRollbackTransceiversWithSameMids)2110 TEST_F(PeerConnectionJsepTest, ImplicitlyRollbackTransceiversWithSameMids) {
2111   RTCConfiguration config;
2112   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
2113   config.enable_implicit_rollback = true;
2114   auto caller = CreatePeerConnection(config);
2115   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2116   auto callee = CreatePeerConnection(config);
2117   callee->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2118   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2119   auto initial_mid = callee->pc()->GetTransceivers()[0]->mid();
2120   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2121   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 2u);
2122   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->mid(), absl::nullopt);
2123   EXPECT_EQ(callee->pc()->GetTransceivers()[1]->mid(),
2124             caller->pc()->GetTransceivers()[0]->mid());
2125   EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal());  // Go to stable.
2126   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2127   EXPECT_NE(callee->pc()->GetTransceivers()[0]->mid(), initial_mid);
2128 }
2129 
TEST_F(PeerConnectionJsepTest,RollbackToNegotiatedStableState)2130 TEST_F(PeerConnectionJsepTest, RollbackToNegotiatedStableState) {
2131   RTCConfiguration config;
2132   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
2133   config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle;
2134   auto caller = CreatePeerConnection(config);
2135   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2136   auto callee = CreatePeerConnection(config);
2137   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2138   EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal());
2139   caller->AddVideoTrack("a");
2140   callee->AddVideoTrack("b");
2141   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2142   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 2u);
2143   auto audio_transport =
2144       callee->pc()->GetTransceivers()[0]->sender()->dtls_transport();
2145   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->sender()->dtls_transport(),
2146             callee->pc()->GetTransceivers()[1]->sender()->dtls_transport());
2147   EXPECT_NE(callee->pc()->GetTransceivers()[1]->sender()->dtls_transport(),
2148             nullptr);
2149   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
2150   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->sender()->dtls_transport(),
2151             audio_transport);  // Audio must remain working after rollback.
2152   EXPECT_EQ(callee->pc()->GetTransceivers()[1]->sender()->dtls_transport(),
2153             nullptr);
2154   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2155 
2156   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->sender()->dtls_transport(),
2157             audio_transport);  // Audio transport is still the same.
2158 }
2159 
TEST_F(PeerConnectionJsepTest,RollbackHasToDestroyTransport)2160 TEST_F(PeerConnectionJsepTest, RollbackHasToDestroyTransport) {
2161   RTCConfiguration config;
2162   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
2163   config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle;
2164   auto pc = CreatePeerConnection(config);
2165   pc->AddAudioTrack("a");
2166   pc->AddVideoTrack("b");
2167   EXPECT_TRUE(pc->CreateOfferAndSetAsLocal());
2168   auto offer = pc->CreateOffer();
2169   EXPECT_EQ(pc->pc()->GetTransceivers().size(), 2u);
2170   auto audio_transport =
2171       pc->pc()->GetTransceivers()[0]->sender()->dtls_transport();
2172   EXPECT_EQ(pc->pc()->GetTransceivers()[0]->sender()->dtls_transport(),
2173             pc->pc()->GetTransceivers()[1]->sender()->dtls_transport());
2174   EXPECT_NE(pc->pc()->GetTransceivers()[1]->sender()->dtls_transport(),
2175             nullptr);
2176   EXPECT_TRUE(pc->SetRemoteDescription(pc->CreateRollback()));
2177   EXPECT_TRUE(pc->SetLocalDescription(std::move(offer)));
2178   EXPECT_NE(pc->pc()->GetTransceivers()[0]->sender()->dtls_transport(),
2179             nullptr);
2180   EXPECT_NE(pc->pc()->GetTransceivers()[0]->sender()->dtls_transport(),
2181             audio_transport);
2182 }
2183 
TEST_F(PeerConnectionJsepTest,RollbackLocalDirectionChange)2184 TEST_F(PeerConnectionJsepTest, RollbackLocalDirectionChange) {
2185   auto caller = CreatePeerConnection();
2186   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2187   auto callee = CreatePeerConnection();
2188   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2189   EXPECT_TRUE(
2190       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
2191   callee->AddAudioTrack("a");
2192   callee->pc()->GetTransceivers()[0]->SetDirectionWithError(
2193       RtpTransceiverDirection::kSendOnly);
2194   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2195   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2196   auto audio_transport =
2197       callee->pc()->GetTransceivers()[0]->receiver()->dtls_transport();
2198   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
2199   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->direction(),
2200             RtpTransceiverDirection::kSendOnly);
2201   // One way audio must remain working after rollback as local direction change
2202   // comes in effect after completing full negotiation round.
2203   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->receiver()->dtls_transport(),
2204             audio_transport);
2205 }
2206 
TEST_F(PeerConnectionJsepTest,RollbackRemoteDirectionChange)2207 TEST_F(PeerConnectionJsepTest, RollbackRemoteDirectionChange) {
2208   auto caller = CreatePeerConnection();
2209   auto caller_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2210   auto callee = CreatePeerConnection();
2211   callee->AddAudioTrack("a");
2212   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2213   EXPECT_TRUE(
2214       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
2215   // In stable make remote audio receive only.
2216   caller_transceiver->SetDirectionWithError(RtpTransceiverDirection::kRecvOnly);
2217   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2218   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2219   // The direction attribute is not modified by the offer.
2220   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->direction(),
2221             RtpTransceiverDirection::kSendRecv);
2222   auto audio_transport =
2223       callee->pc()->GetTransceivers()[0]->sender()->dtls_transport();
2224   EXPECT_EQ(callee->observer()->add_track_events_.size(), 1u);
2225   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 1u);
2226   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
2227   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2228   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->direction(),
2229             RtpTransceiverDirection::kSendRecv);
2230   // One way audio must remain working after rollback.
2231   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->sender()->dtls_transport(),
2232             audio_transport);
2233   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 1u);
2234 }
2235 
TEST_F(PeerConnectionJsepTest,RollbackRestoresFiredDirectionAndOnTrackCanFireAgain)2236 TEST_F(PeerConnectionJsepTest,
2237        RollbackRestoresFiredDirectionAndOnTrackCanFireAgain) {
2238   auto caller = CreatePeerConnection();
2239   auto caller_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2240   auto callee = CreatePeerConnection();
2241   callee->AddAudioTrack("a");
2242   ASSERT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2243   auto callee_transceiver = callee->pc()->GetTransceivers()[0];
2244   EXPECT_FALSE(callee_transceiver->fired_direction().has_value());
2245   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2246   EXPECT_TRUE(callee_transceiver->fired_direction().has_value());
2247   EXPECT_EQ(callee->observer()->add_track_events_.size(), 1u);
2248   // The existing transceiver becomes associated. Because it already exists,
2249   // rolling it back does not remove the transceiver, so if ontrack fires again
2250   // later it will be because the transceiver's internal states were restored
2251   // rather than due to the creation of a new transceiver.
2252   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2253 
2254   // Rollback: the transceiver is no longer receiving.
2255   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
2256   EXPECT_FALSE(callee_transceiver->fired_direction().has_value());
2257   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2258 
2259   // Set the remote offer again: ontrack should fire on the same transceiver.
2260   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2261   EXPECT_TRUE(callee_transceiver->fired_direction().has_value());
2262   EXPECT_EQ(callee->observer()->add_track_events_.size(), 2u);
2263   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 1u);
2264 }
2265 
TEST_F(PeerConnectionJsepTest,RollbackFromInactiveToReceivingMakesOnTrackFire)2266 TEST_F(PeerConnectionJsepTest,
2267        RollbackFromInactiveToReceivingMakesOnTrackFire) {
2268   auto caller = CreatePeerConnection();
2269   auto caller_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2270   auto callee = CreatePeerConnection();
2271   // Perform full O/A so that transceiver is associated. Ontrack fires.
2272   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2273   EXPECT_EQ(callee->observer()->add_track_events_.size(), 1u);
2274   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 0u);
2275   ASSERT_TRUE(
2276       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
2277 
2278   // Start negotiating to make the transceiver inactive. Onremovetrack fires.
2279   caller_transceiver->SetDirectionWithError(RtpTransceiverDirection::kInactive);
2280   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2281   EXPECT_EQ(callee->observer()->add_track_events_.size(), 1u);
2282   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 1u);
2283 
2284   // Rollback the inactivation. Ontrack should fire again.
2285   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateRollback()));
2286   EXPECT_EQ(callee->observer()->add_track_events_.size(), 2u);
2287   EXPECT_EQ(callee->observer()->remove_track_events_.size(), 1u);
2288 }
2289 
TEST_F(PeerConnectionJsepTest,RollbackAfterMultipleSLD)2290 TEST_F(PeerConnectionJsepTest, RollbackAfterMultipleSLD) {
2291   auto callee = CreatePeerConnection();
2292   callee->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2293   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2294   callee->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2295   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2296   callee->observer()->clear_legacy_renegotiation_needed();
2297   callee->observer()->clear_latest_negotiation_needed_event();
2298   EXPECT_TRUE(callee->SetRemoteDescription(callee->CreateRollback()));
2299   EXPECT_TRUE(callee->observer()->legacy_renegotiation_needed());
2300   EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
2301   EXPECT_EQ(callee->pc()->GetTransceivers().size(), 2u);
2302   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->mid(), absl::nullopt);
2303   EXPECT_EQ(callee->pc()->GetTransceivers()[1]->mid(), absl::nullopt);
2304 }
2305 
TEST_F(PeerConnectionJsepTest,NoRollbackNeeded)2306 TEST_F(PeerConnectionJsepTest, NoRollbackNeeded) {
2307   auto caller = CreatePeerConnection();
2308   caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2309   auto callee = CreatePeerConnection();
2310   callee->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
2311   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
2312   EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
2313   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2314   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2315 }
2316 
TEST_F(PeerConnectionJsepTest,RollbackMultipleStreamChanges)2317 TEST_F(PeerConnectionJsepTest, RollbackMultipleStreamChanges) {
2318   auto callee = CreatePeerConnection();
2319   auto caller = CreatePeerConnection();
2320   caller->AddAudioTrack("a_1", {"id_1"});
2321   caller->AddVideoTrack("v_0", {"id_0"});  // Provide an extra stream id.
2322   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2323   EXPECT_TRUE(
2324       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
2325   caller->pc()->GetTransceivers()[0]->sender()->SetStreams({"id_2"});
2326   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2327   caller->pc()->GetTransceivers()[0]->sender()->SetStreams({"id_3"});
2328   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2329   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->receiver()->stream_ids()[0],
2330             "id_3");
2331   EXPECT_TRUE(callee->SetRemoteDescription(callee->CreateRollback()));
2332   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->receiver()->stream_ids().size(),
2333             1u);
2334   EXPECT_EQ(callee->pc()->GetTransceivers()[0]->receiver()->stream_ids()[0],
2335             "id_1");
2336 }
2337 
TEST_F(PeerConnectionJsepTest,DataChannelImplicitRollback)2338 TEST_F(PeerConnectionJsepTest, DataChannelImplicitRollback) {
2339   RTCConfiguration config;
2340   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
2341   config.enable_implicit_rollback = true;
2342   auto caller = CreatePeerConnection(config);
2343   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2344   auto callee = CreatePeerConnection(config);
2345   callee->CreateDataChannel("dummy");
2346   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2347   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2348   EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal());
2349   EXPECT_TRUE(callee->observer()->legacy_renegotiation_needed());
2350   EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
2351   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2352 }
2353 
TEST_F(PeerConnectionJsepTest,RollbackRemoteDataChannelThenAddTransceiver)2354 TEST_F(PeerConnectionJsepTest, RollbackRemoteDataChannelThenAddTransceiver) {
2355   auto caller = CreatePeerConnection();
2356   auto callee = CreatePeerConnection();
2357   caller->CreateDataChannel("dummy");
2358   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2359   EXPECT_TRUE(callee->SetRemoteDescription(callee->CreateRollback()));
2360   callee->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2361   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2362 }
2363 
TEST_F(PeerConnectionJsepTest,RollbackRemoteDataChannelThenAddTransceiverAndDataChannel)2364 TEST_F(PeerConnectionJsepTest,
2365        RollbackRemoteDataChannelThenAddTransceiverAndDataChannel) {
2366   auto caller = CreatePeerConnection();
2367   auto callee = CreatePeerConnection();
2368   caller->CreateDataChannel("dummy");
2369   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2370   EXPECT_TRUE(callee->SetRemoteDescription(callee->CreateRollback()));
2371   callee->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2372   callee->CreateDataChannel("dummy");
2373   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2374 }
2375 
TEST_F(PeerConnectionJsepTest,RollbackRemoteDataChannelThenAddDataChannel)2376 TEST_F(PeerConnectionJsepTest, RollbackRemoteDataChannelThenAddDataChannel) {
2377   auto caller = CreatePeerConnection();
2378   auto callee = CreatePeerConnection();
2379   caller->CreateDataChannel("dummy");
2380   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2381   EXPECT_TRUE(callee->SetRemoteDescription(callee->CreateRollback()));
2382   callee->CreateDataChannel("dummy");
2383   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2384 }
2385 
TEST_F(PeerConnectionJsepTest,RollbackRemoteTransceiverThenAddDataChannel)2386 TEST_F(PeerConnectionJsepTest, RollbackRemoteTransceiverThenAddDataChannel) {
2387   auto caller = CreatePeerConnection();
2388   auto callee = CreatePeerConnection();
2389   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2390   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2391   EXPECT_TRUE(callee->SetRemoteDescription(callee->CreateRollback()));
2392   callee->CreateDataChannel("dummy");
2393   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2394 }
2395 
TEST_F(PeerConnectionJsepTest,RollbackRemoteTransceiverThenAddDataChannelAndTransceiver)2396 TEST_F(PeerConnectionJsepTest,
2397        RollbackRemoteTransceiverThenAddDataChannelAndTransceiver) {
2398   auto caller = CreatePeerConnection();
2399   auto callee = CreatePeerConnection();
2400   caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2401   EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
2402   EXPECT_TRUE(callee->SetRemoteDescription(callee->CreateRollback()));
2403   callee->CreateDataChannel("dummy");
2404   callee->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
2405   EXPECT_TRUE(callee->CreateOfferAndSetAsLocal());
2406 }
2407 
2408 }  // namespace webrtc
2409