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