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