blob: 0ba96e1a3b99762a064f2a064f45d21bbfdfe916 [file] [log] [blame]
Steve Antondcc3c022017-12-22 16:02:54 -08001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "api/audio_codecs/builtin_audio_decoder_factory.h"
12#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Steve Antonfa2260d2017-12-28 16:38:23 -080013#include "media/engine/webrtcmediaengine.h"
14#include "modules/audio_processing/include/audio_processing.h"
Steve Antondcc3c022017-12-22 16:02:54 -080015#include "pc/mediasession.h"
Steve Antonfa2260d2017-12-28 16:38:23 -080016#include "pc/peerconnectionfactory.h"
Steve Antondcc3c022017-12-22 16:02:54 -080017#include "pc/peerconnectionwrapper.h"
18#include "pc/sdputils.h"
19#ifdef WEBRTC_ANDROID
20#include "pc/test/androidtestinitializer.h"
21#endif
22#include "pc/test/fakeaudiocapturemodule.h"
Steve Antonfa2260d2017-12-28 16:38:23 -080023#include "pc/test/fakesctptransport.h"
Steve Antondcc3c022017-12-22 16:02:54 -080024#include "rtc_base/gunit.h"
25#include "rtc_base/ptr_util.h"
26#include "rtc_base/virtualsocketserver.h"
27#include "test/gmock.h"
28
29// This file contains tests that ensure the PeerConnection's implementation of
30// CreateOffer/CreateAnswer/SetLocalDescription/SetRemoteDescription conform
31// to the JavaScript Session Establishment Protocol (JSEP).
32// For now these semantics are only available when configuring the
33// PeerConnection with Unified Plan, but eventually that will be the default.
34
35namespace webrtc {
36
37using cricket::MediaContentDescription;
38using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
39using ::testing::Values;
40using ::testing::Combine;
41using ::testing::ElementsAre;
Steve Antonef65ef12018-01-10 17:15:20 -080042using ::testing::UnorderedElementsAre;
Steve Antondcc3c022017-12-22 16:02:54 -080043
Steve Antonfa2260d2017-12-28 16:38:23 -080044class PeerConnectionFactoryForJsepTest : public PeerConnectionFactory {
45 public:
46 PeerConnectionFactoryForJsepTest()
47 : PeerConnectionFactory(
48 rtc::Thread::Current(),
49 rtc::Thread::Current(),
50 rtc::Thread::Current(),
51 rtc::WrapUnique(cricket::WebRtcMediaEngineFactory::Create(
52 FakeAudioCaptureModule::Create(),
53 CreateBuiltinAudioEncoderFactory(),
54 CreateBuiltinAudioDecoderFactory(),
55 nullptr,
56 nullptr,
57 nullptr,
Ivo Creusen62337e52018-01-09 14:17:33 +010058 AudioProcessingBuilder().Create())),
Steve Antonfa2260d2017-12-28 16:38:23 -080059 CreateCallFactory(),
60 nullptr) {}
61
62 std::unique_ptr<cricket::SctpTransportInternalFactory>
63 CreateSctpTransportInternalFactory() {
64 return rtc::MakeUnique<FakeSctpTransportFactory>();
65 }
66};
67
Steve Antondcc3c022017-12-22 16:02:54 -080068class PeerConnectionJsepTest : public ::testing::Test {
69 protected:
70 typedef std::unique_ptr<PeerConnectionWrapper> WrapperPtr;
71
72 PeerConnectionJsepTest()
73 : vss_(new rtc::VirtualSocketServer()), main_(vss_.get()) {
74#ifdef WEBRTC_ANDROID
75 InitializeAndroidObjects();
76#endif
Steve Antondcc3c022017-12-22 16:02:54 -080077 }
78
79 WrapperPtr CreatePeerConnection() {
80 RTCConfiguration config;
81 config.sdp_semantics = SdpSemantics::kUnifiedPlan;
82 return CreatePeerConnection(config);
83 }
84
85 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
Steve Antonfa2260d2017-12-28 16:38:23 -080086 rtc::scoped_refptr<PeerConnectionFactory> pc_factory(
87 new rtc::RefCountedObject<PeerConnectionFactoryForJsepTest>());
88 RTC_CHECK(pc_factory->Initialize());
Steve Antondcc3c022017-12-22 16:02:54 -080089 auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
Steve Antonfa2260d2017-12-28 16:38:23 -080090 auto pc = pc_factory->CreatePeerConnection(config, nullptr, nullptr,
91 observer.get());
Steve Antondcc3c022017-12-22 16:02:54 -080092 if (!pc) {
93 return nullptr;
94 }
95
Steve Antonfa2260d2017-12-28 16:38:23 -080096 return rtc::MakeUnique<PeerConnectionWrapper>(pc_factory, pc,
Steve Antondcc3c022017-12-22 16:02:54 -080097 std::move(observer));
98 }
99
100 std::unique_ptr<rtc::VirtualSocketServer> vss_;
101 rtc::AutoSocketServerThread main_;
Steve Antondcc3c022017-12-22 16:02:54 -0800102};
103
104// Tests for JSEP initial offer generation.
105
106// Test that an offer created by a PeerConnection with no transceivers generates
107// no media sections.
108TEST_F(PeerConnectionJsepTest, EmptyInitialOffer) {
109 auto caller = CreatePeerConnection();
Steve Antonfa2260d2017-12-28 16:38:23 -0800110
Steve Antondcc3c022017-12-22 16:02:54 -0800111 auto offer = caller->CreateOffer();
Steve Antonfa2260d2017-12-28 16:38:23 -0800112 ASSERT_EQ(0u, offer->description()->contents().size());
Steve Antondcc3c022017-12-22 16:02:54 -0800113}
114
115// Test that an initial offer with one audio track generates one audio media
116// section.
117TEST_F(PeerConnectionJsepTest, AudioOnlyInitialOffer) {
118 auto caller = CreatePeerConnection();
119 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Steve Antondcc3c022017-12-22 16:02:54 -0800120
Steve Antonfa2260d2017-12-28 16:38:23 -0800121 auto offer = caller->CreateOffer();
Steve Antondcc3c022017-12-22 16:02:54 -0800122 auto contents = offer->description()->contents();
123 ASSERT_EQ(1u, contents.size());
124 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, contents[0].media_description()->type());
125}
126
127// Test than an initial offer with one video track generates one video media
128// section
129TEST_F(PeerConnectionJsepTest, VideoOnlyInitialOffer) {
130 auto caller = CreatePeerConnection();
131 caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
Steve Antondcc3c022017-12-22 16:02:54 -0800132
Steve Antonfa2260d2017-12-28 16:38:23 -0800133 auto offer = caller->CreateOffer();
Steve Antondcc3c022017-12-22 16:02:54 -0800134 auto contents = offer->description()->contents();
135 ASSERT_EQ(1u, contents.size());
136 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, contents[0].media_description()->type());
137}
138
Steve Antonfa2260d2017-12-28 16:38:23 -0800139// Test that an initial offer with one data channel generates one data media
140// section.
141TEST_F(PeerConnectionJsepTest, DataOnlyInitialOffer) {
142 auto caller = CreatePeerConnection();
143 caller->CreateDataChannel("dc");
144
145 auto offer = caller->CreateOffer();
146 auto contents = offer->description()->contents();
147 ASSERT_EQ(1u, contents.size());
148 EXPECT_EQ(cricket::MEDIA_TYPE_DATA, contents[0].media_description()->type());
149}
150
151// Test that creating multiple data channels only results in one data section
152// generated in the offer.
153TEST_F(PeerConnectionJsepTest, MultipleDataChannelsCreateOnlyOneDataSection) {
154 auto caller = CreatePeerConnection();
155 caller->CreateDataChannel("first");
156 caller->CreateDataChannel("second");
157 caller->CreateDataChannel("third");
158
159 auto offer = caller->CreateOffer();
160 ASSERT_EQ(1u, offer->description()->contents().size());
161}
162
Steve Antondcc3c022017-12-22 16:02:54 -0800163// Test that multiple media sections in the initial offer are ordered in the
164// order the transceivers were added to the PeerConnection. This is required by
165// JSEP section 5.2.1.
166TEST_F(PeerConnectionJsepTest, MediaSectionsInInitialOfferOrderedCorrectly) {
167 auto caller = CreatePeerConnection();
168 caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
169 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
170 RtpTransceiverInit init;
171 init.direction = RtpTransceiverDirection::kSendOnly;
172 caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
Steve Antondcc3c022017-12-22 16:02:54 -0800173
Steve Antonfa2260d2017-12-28 16:38:23 -0800174 auto offer = caller->CreateOffer();
Steve Antondcc3c022017-12-22 16:02:54 -0800175 auto contents = offer->description()->contents();
176 ASSERT_EQ(3u, contents.size());
177
178 const MediaContentDescription* media_description1 =
179 contents[0].media_description();
180 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, media_description1->type());
181 EXPECT_EQ(RtpTransceiverDirection::kSendRecv,
182 media_description1->direction());
183
184 const MediaContentDescription* media_description2 =
185 contents[1].media_description();
186 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, media_description2->type());
187 EXPECT_EQ(RtpTransceiverDirection::kSendRecv,
188 media_description2->direction());
189
190 const MediaContentDescription* media_description3 =
191 contents[2].media_description();
192 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, media_description3->type());
193 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
194 media_description3->direction());
195}
196
197// Test that media sections in the initial offer have different mids.
198TEST_F(PeerConnectionJsepTest, MediaSectionsInInitialOfferHaveDifferentMids) {
199 auto caller = CreatePeerConnection();
200 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
201 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Steve Antonfa2260d2017-12-28 16:38:23 -0800202
Steve Antondcc3c022017-12-22 16:02:54 -0800203 auto offer = caller->CreateOffer();
Steve Antondcc3c022017-12-22 16:02:54 -0800204 auto contents = offer->description()->contents();
205 ASSERT_EQ(2u, contents.size());
206 EXPECT_NE(contents[0].name, contents[1].name);
207}
208
209TEST_F(PeerConnectionJsepTest,
210 StoppedTransceiverHasNoMediaSectionInInitialOffer) {
211 auto caller = CreatePeerConnection();
212 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
213 transceiver->Stop();
214
215 auto offer = caller->CreateOffer();
216 EXPECT_EQ(0u, offer->description()->contents().size());
217}
218
219// Tests for JSEP SetLocalDescription with a local offer.
220
221TEST_F(PeerConnectionJsepTest, SetLocalEmptyOfferCreatesNoTransceivers) {
222 auto caller = CreatePeerConnection();
Steve Antonfa2260d2017-12-28 16:38:23 -0800223
Steve Antondcc3c022017-12-22 16:02:54 -0800224 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
225
226 EXPECT_THAT(caller->pc()->GetTransceivers(), ElementsAre());
227 EXPECT_THAT(caller->pc()->GetSenders(), ElementsAre());
228 EXPECT_THAT(caller->pc()->GetReceivers(), ElementsAre());
229}
230
231TEST_F(PeerConnectionJsepTest, SetLocalOfferSetsTransceiverMid) {
232 auto caller = CreatePeerConnection();
233 auto audio_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
234 auto video_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
235
236 auto offer = caller->CreateOffer();
237 std::string audio_mid = offer->description()->contents()[0].name;
238 std::string video_mid = offer->description()->contents()[1].name;
239
240 ASSERT_TRUE(caller->SetLocalDescription(std::move(offer)));
241
242 EXPECT_EQ(audio_mid, audio_transceiver->mid());
243 EXPECT_EQ(video_mid, video_transceiver->mid());
244}
245
Steve Anton02ee47c2018-01-10 16:26:06 -0800246TEST_F(PeerConnectionJsepTest, SetLocalOfferFailsWithNoTrackInMediaSection) {
247 auto caller = CreatePeerConnection();
248 caller->AddAudioTrack("audio");
249
250 auto offer = caller->CreateOffer();
251 auto& contents = offer->description()->contents();
252 ASSERT_EQ(1u, contents.size());
253 contents[0].description->mutable_streams().clear();
254
255 ASSERT_FALSE(caller->SetLocalDescription(std::move(offer)));
256}
257
Steve Antondcc3c022017-12-22 16:02:54 -0800258// Tests for JSEP SetRemoteDescription with a remote offer.
259
260// Test that setting a remote offer with sendrecv audio and video creates two
261// transceivers, one for receiving audio and one for receiving video.
262TEST_F(PeerConnectionJsepTest, SetRemoteOfferCreatesTransceivers) {
263 auto caller = CreatePeerConnection();
264 auto caller_audio = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
265 auto caller_video = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
266 auto callee = CreatePeerConnection();
267
268 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
269
270 auto transceivers = callee->pc()->GetTransceivers();
271 ASSERT_EQ(2u, transceivers.size());
272 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO,
273 transceivers[0]->receiver()->media_type());
274 EXPECT_EQ(caller_audio->mid(), transceivers[0]->mid());
275 EXPECT_EQ(RtpTransceiverDirection::kRecvOnly, transceivers[0]->direction());
276 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO,
277 transceivers[1]->receiver()->media_type());
278 EXPECT_EQ(caller_video->mid(), transceivers[1]->mid());
279 EXPECT_EQ(RtpTransceiverDirection::kRecvOnly, transceivers[1]->direction());
280}
281
282// Test that setting a remote offer with an audio track will reuse the
283// transceiver created for a local audio track added by AddTrack.
284// This is specified in JSEP section 5.10 (Applying a Remote Description). The
285// intent is to preserve backwards compatibility with clients who only use the
286// AddTrack API.
287TEST_F(PeerConnectionJsepTest, SetRemoteOfferReusesTransceiverFromAddTrack) {
288 auto caller = CreatePeerConnection();
289 caller->AddAudioTrack("a");
290 auto caller_audio = caller->pc()->GetTransceivers()[0];
291 auto callee = CreatePeerConnection();
292 callee->AddAudioTrack("a");
293
294 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
295
296 auto transceivers = callee->pc()->GetTransceivers();
297 ASSERT_EQ(1u, transceivers.size());
298 EXPECT_EQ(MediaStreamTrackInterface::kAudioKind,
299 transceivers[0]->receiver()->track()->kind());
300 EXPECT_EQ(caller_audio->mid(), transceivers[0]->mid());
301}
302
303// Test that setting a remote offer with an audio track marked sendonly will not
304// reuse a transceiver created by AddTrack. JSEP only allows the transceiver to
305// be reused if the offer direction is sendrecv or recvonly.
306TEST_F(PeerConnectionJsepTest,
307 SetRemoteOfferDoesNotReuseTransceiverIfDirectionSendOnly) {
308 auto caller = CreatePeerConnection();
309 caller->AddAudioTrack("a");
310 auto caller_audio = caller->pc()->GetTransceivers()[0];
311 caller_audio->SetDirection(RtpTransceiverDirection::kSendOnly);
312 auto callee = CreatePeerConnection();
313 callee->AddAudioTrack("a");
314
315 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
316
317 auto transceivers = callee->pc()->GetTransceivers();
318 ASSERT_EQ(2u, transceivers.size());
319 EXPECT_EQ(rtc::nullopt, transceivers[0]->mid());
320 EXPECT_EQ(caller_audio->mid(), transceivers[1]->mid());
321}
322
323// Test that setting a remote offer with an audio track will not reuse a
324// transceiver added by AddTransceiver. The logic for reusing a transceiver is
325// specific to those added by AddTrack and is tested above.
326TEST_F(PeerConnectionJsepTest,
327 SetRemoteOfferDoesNotReuseTransceiverFromAddTransceiver) {
328 auto caller = CreatePeerConnection();
329 caller->AddAudioTrack("a");
330 auto callee = CreatePeerConnection();
331 auto transceiver = callee->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
332
333 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
334
335 auto transceivers = callee->pc()->GetTransceivers();
336 ASSERT_EQ(2u, transceivers.size());
337 EXPECT_EQ(rtc::nullopt, transceivers[0]->mid());
338 EXPECT_EQ(caller->pc()->GetTransceivers()[0]->mid(), transceivers[1]->mid());
339 EXPECT_EQ(MediaStreamTrackInterface::kAudioKind,
340 transceivers[1]->receiver()->track()->kind());
341}
342
343// Test that setting a remote offer with an audio track will not reuse a
344// transceiver created for a local video track added by AddTrack.
345TEST_F(PeerConnectionJsepTest,
346 SetRemoteOfferDoesNotReuseTransceiverOfWrongType) {
347 auto caller = CreatePeerConnection();
348 caller->AddAudioTrack("a");
349 auto callee = CreatePeerConnection();
350 auto video_sender = callee->AddVideoTrack("v");
351
352 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
353
354 auto transceivers = callee->pc()->GetTransceivers();
355 ASSERT_EQ(2u, transceivers.size());
356 EXPECT_EQ(rtc::nullopt, transceivers[0]->mid());
357 EXPECT_EQ(caller->pc()->GetTransceivers()[0]->mid(), transceivers[1]->mid());
358 EXPECT_EQ(MediaStreamTrackInterface::kAudioKind,
359 transceivers[1]->receiver()->track()->kind());
360}
361
362// Test that setting a remote offer with an audio track will not reuse a
363// stopped transceiver.
364TEST_F(PeerConnectionJsepTest, SetRemoteOfferDoesNotReuseStoppedTransceiver) {
365 auto caller = CreatePeerConnection();
366 caller->AddAudioTrack("a");
367 auto callee = CreatePeerConnection();
368 callee->AddAudioTrack("a");
369 callee->pc()->GetTransceivers()[0]->Stop();
370
371 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
372
373 auto transceivers = callee->pc()->GetTransceivers();
374 ASSERT_EQ(2u, transceivers.size());
375 EXPECT_EQ(rtc::nullopt, transceivers[0]->mid());
376 EXPECT_TRUE(transceivers[0]->stopped());
377 EXPECT_EQ(caller->pc()->GetTransceivers()[0]->mid(), transceivers[1]->mid());
378 EXPECT_FALSE(transceivers[1]->stopped());
379}
380
381// Test that audio and video transceivers created on the remote side with
382// AddTrack will all be reused if there is the same number of audio/video tracks
383// in the remote offer. Additionally, this tests that transceivers are
384// successfully matched even if they are in a different order on the remote
385// side.
386TEST_F(PeerConnectionJsepTest, SetRemoteOfferReusesTransceiversOfBothTypes) {
387 auto caller = CreatePeerConnection();
388 caller->AddVideoTrack("v");
389 caller->AddAudioTrack("a");
390 auto callee = CreatePeerConnection();
391 callee->AddAudioTrack("a");
392 callee->AddVideoTrack("v");
393
394 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
395
396 auto caller_transceivers = caller->pc()->GetTransceivers();
397 auto callee_transceivers = callee->pc()->GetTransceivers();
398 ASSERT_EQ(2u, callee_transceivers.size());
399 EXPECT_EQ(caller_transceivers[0]->mid(), callee_transceivers[1]->mid());
400 EXPECT_EQ(caller_transceivers[1]->mid(), callee_transceivers[0]->mid());
401}
402
403// Tests for JSEP initial CreateAnswer.
404
405// Test that the answer to a remote offer creates media sections for each
406// offered media in the same order and with the same mids.
407TEST_F(PeerConnectionJsepTest, CreateAnswerHasSameMidsAsOffer) {
408 auto caller = CreatePeerConnection();
409 auto first_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
410 auto second_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
411 auto third_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
Steve Antonfa2260d2017-12-28 16:38:23 -0800412 caller->CreateDataChannel("dc");
Steve Antondcc3c022017-12-22 16:02:54 -0800413 auto callee = CreatePeerConnection();
414
Steve Antonfa2260d2017-12-28 16:38:23 -0800415 auto offer = caller->CreateOffer();
416 const auto* offer_data = cricket::GetFirstDataContent(offer->description());
417 ASSERT_TRUE(
418 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
419 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
Steve Antondcc3c022017-12-22 16:02:54 -0800420
421 auto answer = callee->CreateAnswer();
422 auto contents = answer->description()->contents();
Steve Antonfa2260d2017-12-28 16:38:23 -0800423 ASSERT_EQ(4u, contents.size());
Steve Antondcc3c022017-12-22 16:02:54 -0800424 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, contents[0].media_description()->type());
Steve Antonfa2260d2017-12-28 16:38:23 -0800425 EXPECT_EQ(first_transceiver->mid(), contents[0].name);
Steve Antondcc3c022017-12-22 16:02:54 -0800426 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, contents[1].media_description()->type());
Steve Antonfa2260d2017-12-28 16:38:23 -0800427 EXPECT_EQ(second_transceiver->mid(), contents[1].name);
Steve Antondcc3c022017-12-22 16:02:54 -0800428 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, contents[2].media_description()->type());
Steve Antonfa2260d2017-12-28 16:38:23 -0800429 EXPECT_EQ(third_transceiver->mid(), contents[2].name);
430 EXPECT_EQ(cricket::MEDIA_TYPE_DATA, contents[3].media_description()->type());
431 EXPECT_EQ(offer_data->name, contents[3].name);
Steve Antondcc3c022017-12-22 16:02:54 -0800432}
433
434// Test that an answering media section is marked as rejected if the underlying
435// transceiver has been stopped.
436TEST_F(PeerConnectionJsepTest, CreateAnswerRejectsStoppedTransceiver) {
437 auto caller = CreatePeerConnection();
438 caller->AddAudioTrack("a");
439 auto callee = CreatePeerConnection();
440
441 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
442
443 callee->pc()->GetTransceivers()[0]->Stop();
444
445 auto answer = callee->CreateAnswer();
446 auto contents = answer->description()->contents();
447 ASSERT_EQ(1u, contents.size());
448 EXPECT_TRUE(contents[0].rejected);
449}
450
451// Test that CreateAnswer will generate media sections which will only send or
452// receive if the offer indicates it can do the reciprocating direction.
453// The full matrix is tested more extensively in MediaSession.
454TEST_F(PeerConnectionJsepTest, CreateAnswerNegotiatesDirection) {
455 auto caller = CreatePeerConnection();
456 RtpTransceiverInit init;
457 init.direction = RtpTransceiverDirection::kSendOnly;
458 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
459 auto callee = CreatePeerConnection();
460 callee->AddAudioTrack("a");
461
462 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
463
464 auto answer = callee->CreateAnswer();
465 auto contents = answer->description()->contents();
466 ASSERT_EQ(1u, contents.size());
467 EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
468 contents[0].media_description()->direction());
469}
470
471// Tests for JSEP SetLocalDescription with a local answer.
472// Note that these test only the additional behaviors not covered by
473// SetLocalDescription with a local offer.
474
475// Test that SetLocalDescription with an answer sets the current_direction
476// property of the transceivers mentioned in the session description.
477TEST_F(PeerConnectionJsepTest, SetLocalAnswerUpdatesCurrentDirection) {
478 auto caller = CreatePeerConnection();
479 auto caller_audio = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
480 caller_audio->SetDirection(RtpTransceiverDirection::kRecvOnly);
481 auto callee = CreatePeerConnection();
482 callee->AddAudioTrack("a");
483
484 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
485 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
486
487 auto transceivers = callee->pc()->GetTransceivers();
488 ASSERT_EQ(1u, transceivers.size());
489 // Since the offer was recvonly and the transceiver direction is sendrecv,
490 // the negotiated direction will be sendonly.
491 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
492 transceivers[0]->current_direction());
493}
494
495// Tests for JSEP SetRemoteDescription with a remote answer.
496// Note that these test only the additional behaviors not covered by
497// SetRemoteDescription with a remote offer.
498
499TEST_F(PeerConnectionJsepTest, SetRemoteAnswerUpdatesCurrentDirection) {
500 auto caller = CreatePeerConnection();
501 caller->AddAudioTrack("a");
502 auto callee = CreatePeerConnection();
503 callee->AddAudioTrack("a");
504 auto callee_audio = callee->pc()->GetTransceivers()[0];
505 callee_audio->SetDirection(RtpTransceiverDirection::kSendOnly);
506
507 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
508 ASSERT_TRUE(
509 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
510
511 auto transceivers = caller->pc()->GetTransceivers();
512 ASSERT_EQ(1u, transceivers.size());
513 // Since the remote transceiver was set to sendonly, the negotiated direction
514 // in the answer would be sendonly which we apply as recvonly to the local
515 // transceiver.
516 EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
517 transceivers[0]->current_direction());
518}
519
520// Tests for multiple round trips.
521
522// Test that setting a transceiver with the inactive direction does not stop it
523// on either the caller or the callee.
524TEST_F(PeerConnectionJsepTest, SettingTransceiverInactiveDoesNotStopIt) {
525 auto caller = CreatePeerConnection();
526 caller->AddAudioTrack("a");
527 auto callee = CreatePeerConnection();
528 callee->AddAudioTrack("a");
529 callee->pc()->GetTransceivers()[0]->SetDirection(
530 RtpTransceiverDirection::kInactive);
531
532 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
533 ASSERT_TRUE(
534 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
535
536 EXPECT_FALSE(caller->pc()->GetTransceivers()[0]->stopped());
537 EXPECT_FALSE(callee->pc()->GetTransceivers()[0]->stopped());
538}
539
540// Test that if a transceiver had been associated and later stopped, then a
541// media section is still generated for it and the media section is marked as
542// rejected.
543TEST_F(PeerConnectionJsepTest,
544 ReOfferMediaSectionForAssociatedStoppedTransceiverIsRejected) {
545 auto caller = CreatePeerConnection();
546 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
547 auto callee = CreatePeerConnection();
548
549 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
550 ASSERT_TRUE(
551 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
552
553 ASSERT_TRUE(transceiver->mid());
554 transceiver->Stop();
555
556 auto reoffer = caller->CreateOffer();
557 auto contents = reoffer->description()->contents();
558 ASSERT_EQ(1u, contents.size());
559 EXPECT_TRUE(contents[0].rejected);
560}
561
562// Test that stopping an associated transceiver on the caller side will stop the
563// corresponding transceiver on the remote side when the remote offer is
564// applied.
565TEST_F(PeerConnectionJsepTest,
566 StoppingTransceiverInOfferStopsTransceiverOnRemoteSide) {
567 auto caller = CreatePeerConnection();
568 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
569 auto callee = CreatePeerConnection();
570
571 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
572 ASSERT_TRUE(
573 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
574
575 transceiver->Stop();
576
577 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
578
579 auto transceivers = callee->pc()->GetTransceivers();
580 EXPECT_TRUE(transceivers[0]->stopped());
581 EXPECT_TRUE(transceivers[0]->mid());
582}
583
584// Test that CreateOffer will only generate a recycled media section if the
585// transceiver to be recycled has been seen stopped by the other side first.
586TEST_F(PeerConnectionJsepTest,
587 CreateOfferDoesNotRecycleMediaSectionIfFirstStopped) {
588 auto caller = CreatePeerConnection();
589 auto first_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
590 auto callee = CreatePeerConnection();
591
592 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
593 ASSERT_TRUE(
594 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
595
596 auto second_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
597 first_transceiver->Stop();
598
599 auto reoffer = caller->CreateOffer();
600 auto contents = reoffer->description()->contents();
601 ASSERT_EQ(2u, contents.size());
602 EXPECT_TRUE(contents[0].rejected);
603 EXPECT_FALSE(contents[1].rejected);
604}
605
606// Test that the offer/answer and transceivers for both the caller and callee
607// side are generated/updated correctly when recycling an audio/video media
608// section as a media section of either the same or opposite type.
609class RecycleMediaSectionTest
610 : public PeerConnectionJsepTest,
611 public testing::WithParamInterface<
612 std::tuple<cricket::MediaType, cricket::MediaType>> {
613 protected:
614 RecycleMediaSectionTest() {
615 first_type_ = std::get<0>(GetParam());
616 second_type_ = std::get<1>(GetParam());
617 }
618
619 cricket::MediaType first_type_;
620 cricket::MediaType second_type_;
621};
622
623TEST_P(RecycleMediaSectionTest, VerifyOfferAnswerAndTransceivers) {
624 auto caller = CreatePeerConnection();
625 auto first_transceiver = caller->AddTransceiver(first_type_);
626 auto callee = CreatePeerConnection();
627
628 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
629
630 std::string first_mid = *first_transceiver->mid();
631 first_transceiver->Stop();
632
633 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
634
635 auto second_transceiver = caller->AddTransceiver(second_type_);
636
637 // The offer should reuse the previous media section but allocate a new MID
638 // and change the media type.
639 auto offer = caller->CreateOffer();
640 auto offer_contents = offer->description()->contents();
641 ASSERT_EQ(1u, offer_contents.size());
642 EXPECT_FALSE(offer_contents[0].rejected);
643 EXPECT_EQ(second_type_, offer_contents[0].media_description()->type());
644 std::string second_mid = offer_contents[0].name;
645 EXPECT_NE(first_mid, second_mid);
646
647 // Setting the local offer will dissociate the previous transceiver and set
648 // the MID for the new transceiver.
649 ASSERT_TRUE(
650 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
651 EXPECT_EQ(rtc::nullopt, first_transceiver->mid());
652 EXPECT_EQ(second_mid, second_transceiver->mid());
653
654 // Setting the remote offer will dissociate the previous transceiver and
655 // create a new transceiver for the media section.
656 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
657 auto callee_transceivers = callee->pc()->GetTransceivers();
658 ASSERT_EQ(2u, callee_transceivers.size());
659 EXPECT_EQ(rtc::nullopt, callee_transceivers[0]->mid());
660 EXPECT_EQ(first_type_, callee_transceivers[0]->receiver()->media_type());
661 EXPECT_EQ(second_mid, callee_transceivers[1]->mid());
662 EXPECT_EQ(second_type_, callee_transceivers[1]->receiver()->media_type());
663
664 // The answer should have only one media section for the new transceiver.
665 auto answer = callee->CreateAnswer();
666 auto answer_contents = answer->description()->contents();
667 ASSERT_EQ(1u, answer_contents.size());
668 EXPECT_FALSE(answer_contents[0].rejected);
669 EXPECT_EQ(second_mid, answer_contents[0].name);
670 EXPECT_EQ(second_type_, answer_contents[0].media_description()->type());
671
672 // Setting the local answer should succeed.
673 ASSERT_TRUE(
674 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
675
676 // Setting the remote answer should succeed.
677 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
678}
679
680// Test all combinations of audio and video as the first and second media type
681// for the media section. This is needed for full test coverage because
682// MediaSession has separate functions for processing audio and video media
683// sections.
684INSTANTIATE_TEST_CASE_P(
685 PeerConnectionJsepTest,
686 RecycleMediaSectionTest,
687 Combine(Values(cricket::MEDIA_TYPE_AUDIO, cricket::MEDIA_TYPE_VIDEO),
688 Values(cricket::MEDIA_TYPE_AUDIO, cricket::MEDIA_TYPE_VIDEO)));
689
Steve Antonfa2260d2017-12-28 16:38:23 -0800690// Test that a new data channel section will not reuse a recycleable audio or
691// video media section. Additionally, tests that the new section is added to the
692// end of the session description.
693TEST_F(PeerConnectionJsepTest, DataChannelDoesNotRecycleMediaSection) {
694 auto caller = CreatePeerConnection();
695 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
696 auto callee = CreatePeerConnection();
697
698 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
699
700 transceiver->Stop();
701
702 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
703
704 caller->CreateDataChannel("dc");
705
706 auto offer = caller->CreateOffer();
707 auto offer_contents = offer->description()->contents();
708 ASSERT_EQ(2u, offer_contents.size());
709 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO,
710 offer_contents[0].media_description()->type());
711 EXPECT_EQ(cricket::MEDIA_TYPE_DATA,
712 offer_contents[1].media_description()->type());
713
714 ASSERT_TRUE(
715 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
716 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
717
718 auto answer = callee->CreateAnswer();
719 auto answer_contents = answer->description()->contents();
720 ASSERT_EQ(2u, answer_contents.size());
721 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO,
722 answer_contents[0].media_description()->type());
723 EXPECT_EQ(cricket::MEDIA_TYPE_DATA,
724 answer_contents[1].media_description()->type());
725}
726
727// Test that if a new track is added to an existing session that has a data,
728// the new section comes at the end of the new offer, after the existing data
729// section.
730TEST_F(PeerConnectionJsepTest, AudioTrackAddedAfterDataSectionInReoffer) {
731 auto caller = CreatePeerConnection();
732 caller->CreateDataChannel("dc");
733 auto callee = CreatePeerConnection();
734
735 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
736
737 caller->AddAudioTrack("a");
738
739 auto offer = caller->CreateOffer();
740 auto contents = offer->description()->contents();
741 ASSERT_EQ(2u, contents.size());
742 EXPECT_EQ(cricket::MEDIA_TYPE_DATA, contents[0].media_description()->type());
743 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, contents[1].media_description()->type());
744}
745
Steve Antondcc3c022017-12-22 16:02:54 -0800746// Tests for MID properties.
747
748static void RenameSection(size_t mline_index,
749 const std::string& new_mid,
750 SessionDescriptionInterface* sdesc) {
751 cricket::SessionDescription* desc = sdesc->description();
752 std::string old_mid = desc->contents()[mline_index].name;
753 desc->contents()[mline_index].name = new_mid;
754 desc->transport_infos()[mline_index].content_name = new_mid;
755 const cricket::ContentGroup* bundle =
756 desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
757 if (bundle) {
758 cricket::ContentGroup new_bundle = *bundle;
759 if (new_bundle.RemoveContentName(old_mid)) {
760 new_bundle.AddContentName(new_mid);
761 }
762 desc->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
763 desc->AddGroup(new_bundle);
764 }
765}
766
767// Test that two PeerConnections can have a successful offer/answer exchange if
768// the MIDs are changed from the defaults.
769TEST_F(PeerConnectionJsepTest, OfferAnswerWithChangedMids) {
770 constexpr char kFirstMid[] = "nondefaultmid";
771 constexpr char kSecondMid[] = "randommid";
772
773 auto caller = CreatePeerConnection();
774 caller->AddAudioTrack("a");
775 caller->AddAudioTrack("b");
776 auto callee = CreatePeerConnection();
777
778 auto offer = caller->CreateOffer();
779 RenameSection(0, kFirstMid, offer.get());
780 RenameSection(1, kSecondMid, offer.get());
781
782 ASSERT_TRUE(
783 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
784 auto caller_transceivers = caller->pc()->GetTransceivers();
785 EXPECT_EQ(kFirstMid, caller_transceivers[0]->mid());
786 EXPECT_EQ(kSecondMid, caller_transceivers[1]->mid());
787
788 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
789 auto callee_transceivers = callee->pc()->GetTransceivers();
790 EXPECT_EQ(kFirstMid, callee_transceivers[0]->mid());
791 EXPECT_EQ(kSecondMid, callee_transceivers[1]->mid());
792
793 auto answer = callee->CreateAnswer();
794 auto answer_contents = answer->description()->contents();
795 EXPECT_EQ(kFirstMid, answer_contents[0].name);
796 EXPECT_EQ(kSecondMid, answer_contents[1].name);
797
798 ASSERT_TRUE(
799 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
800 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
801}
802
803// Test that CreateOffer will generate a MID that is not already used if the
804// default it would have picked is already taken. This is tested by using a
805// third PeerConnection to determine what the default would be for the second
806// media section then setting that as the first media section's MID.
807TEST_F(PeerConnectionJsepTest, CreateOfferGeneratesUniqueMidIfAlreadyTaken) {
808 // First, find what the default MID is for the second media section.
809 auto pc = CreatePeerConnection();
810 pc->AddAudioTrack("a");
811 pc->AddAudioTrack("b");
812 auto default_offer = pc->CreateOffer();
813 std::string default_second_mid =
814 default_offer->description()->contents()[1].name;
815
816 // Now, do an offer/answer with one track which has the MID set to the default
817 // second MID.
818 auto caller = CreatePeerConnection();
819 caller->AddAudioTrack("a");
820 auto callee = CreatePeerConnection();
821
822 auto offer = caller->CreateOffer();
823 RenameSection(0, default_second_mid, offer.get());
824
825 ASSERT_TRUE(
826 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
827 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
828 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
829
830 // Add a second track and ensure that the MID is different.
831 caller->AddAudioTrack("b");
832
833 auto reoffer = caller->CreateOffer();
834 auto reoffer_contents = reoffer->description()->contents();
835 EXPECT_EQ(default_second_mid, reoffer_contents[0].name);
836 EXPECT_NE(reoffer_contents[0].name, reoffer_contents[1].name);
837}
838
Steve Antonfa2260d2017-12-28 16:38:23 -0800839// Test that if an audio or video section has the default data section MID, then
840// CreateOffer will generate a unique MID for the newly added data section.
841TEST_F(PeerConnectionJsepTest,
842 CreateOfferGeneratesUniqueMidForDataSectionIfAlreadyTaken) {
843 // First, find what the default MID is for the data channel.
844 auto pc = CreatePeerConnection();
845 pc->CreateDataChannel("dc");
846 auto default_offer = pc->CreateOffer();
847 std::string default_data_mid =
848 default_offer->description()->contents()[0].name;
849
850 // Now do an offer/answer with one audio track which has a MID set to the
851 // default data MID.
852 auto caller = CreatePeerConnection();
853 caller->AddAudioTrack("a");
854 auto callee = CreatePeerConnection();
855
856 auto offer = caller->CreateOffer();
857 RenameSection(0, default_data_mid, offer.get());
858
859 ASSERT_TRUE(
860 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
861 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
862 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
863
864 // Add a data channel and ensure that the MID is different.
865 caller->CreateDataChannel("dc");
866
867 auto reoffer = caller->CreateOffer();
868 auto reoffer_contents = reoffer->description()->contents();
869 EXPECT_EQ(default_data_mid, reoffer_contents[0].name);
870 EXPECT_NE(reoffer_contents[0].name, reoffer_contents[1].name);
871}
872
Steve Antondcc3c022017-12-22 16:02:54 -0800873// Test that a reoffer initiated by the callee adds a new track to the caller.
874TEST_F(PeerConnectionJsepTest, CalleeDoesReoffer) {
875 auto caller = CreatePeerConnection();
876 caller->AddAudioTrack("a");
877 auto callee = CreatePeerConnection();
878 callee->AddAudioTrack("a");
879 callee->AddVideoTrack("v");
880
881 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
882
883 EXPECT_EQ(1u, caller->pc()->GetTransceivers().size());
884 EXPECT_EQ(2u, callee->pc()->GetTransceivers().size());
885
886 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
887
888 EXPECT_EQ(2u, caller->pc()->GetTransceivers().size());
889 EXPECT_EQ(2u, callee->pc()->GetTransceivers().size());
890}
891
Steve Anton02ee47c2018-01-10 16:26:06 -0800892// Tests for MSID properties.
893
894// Test that adding a track with AddTrack results in an offer that signals the
895// track's ID.
896TEST_F(PeerConnectionJsepTest, AddingTrackWithAddTrackSpecifiesTrackId) {
897 const std::string kTrackId = "audio_track";
898
899 auto caller = CreatePeerConnection();
900 caller->AddAudioTrack(kTrackId);
901
902 auto offer = caller->CreateOffer();
903 auto contents = offer->description()->contents();
904 ASSERT_EQ(1u, contents.size());
905 auto streams = contents[0].media_description()->streams();
906 ASSERT_EQ(1u, streams.size());
907 EXPECT_EQ(kTrackId, streams[0].id);
908}
909
910// Test that adding a track by calling AddTransceiver then SetTrack results in
911// an offer that does not signal the track's ID and signals a random ID.
912TEST_F(PeerConnectionJsepTest,
913 AddingTrackWithAddTransceiverSpecifiesRandomTrackId) {
914 const std::string kTrackId = "audio_track";
915
916 auto caller = CreatePeerConnection();
917 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
918 transceiver->sender()->SetTrack(caller->CreateAudioTrack(kTrackId));
919
920 auto offer = caller->CreateOffer();
921 auto contents = offer->description()->contents();
922 ASSERT_EQ(1u, contents.size());
923 auto streams = contents[0].media_description()->streams();
924 ASSERT_EQ(1u, streams.size());
925 EXPECT_NE(kTrackId, streams[0].id);
926}
927
928// Test that the callee RtpReceiver created by a call to SetRemoteDescription
929// has its ID set to the signaled track ID.
930TEST_F(PeerConnectionJsepTest,
931 RtpReceiverCreatedBySetRemoteDescriptionHasSignaledTrackId) {
932 const std::string kTrackId = "audio_track";
933
934 auto caller = CreatePeerConnection();
935 auto callee = CreatePeerConnection();
936 caller->AddAudioTrack(kTrackId);
937
938 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
939
940 ASSERT_EQ(1u, callee->pc()->GetReceivers().size());
941 auto receiver = callee->pc()->GetReceivers()[0];
942 EXPECT_EQ(kTrackId, receiver->id());
943}
944
945// Test that if the callee RtpReceiver is reused by a call to
946// SetRemoteDescription, its ID does not change.
947TEST_F(PeerConnectionJsepTest,
948 RtpReceiverCreatedBeforeSetRemoteDescriptionKeepsId) {
949 const std::string kTrackId = "audio_track";
950
951 auto caller = CreatePeerConnection();
952 auto callee = CreatePeerConnection();
953 caller->AddAudioTrack(kTrackId);
954 callee->AddAudioTrack("dummy_track");
955
956 ASSERT_EQ(1u, callee->pc()->GetReceivers().size());
957 auto receiver = callee->pc()->GetReceivers()[0];
958 std::string receiver_id = receiver->id();
959
960 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
961
962 EXPECT_EQ(receiver_id, receiver->id());
963}
964
Steve Antonef65ef12018-01-10 17:15:20 -0800965// Test that setting a remote offer with one track that has no streams fires off
966// the correct OnAddTrack event.
967TEST_F(PeerConnectionJsepTest,
968 SetRemoteOfferWithOneTrackNoStreamFiresOnAddTrack) {
969 const std::string kTrackLabel = "audio_track";
970
971 auto caller = CreatePeerConnection();
972 auto callee = CreatePeerConnection();
973 ASSERT_TRUE(caller->AddAudioTrack(kTrackLabel));
974
975 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
976
977 ASSERT_EQ(callee->observer()->add_track_events_.size(), 1u);
978 EXPECT_EQ(kTrackLabel,
979 callee->observer()->add_track_events_[0].receiver->track()->id());
980 // TODO(bugs.webrtc.org/7933): Also verify that no stream was added to the
981 // receiver.
982}
983
984// Test that setting a remote offer with one track that has one stream fires off
985// the correct OnAddTrack event.
986TEST_F(PeerConnectionJsepTest,
987 SetRemoteOfferWithOneTrackOneStreamFiresOnAddTrack) {
988 const std::string kTrackLabel = "audio_track";
989 const std::string kStreamLabel = "audio_stream";
990
991 auto caller = CreatePeerConnection();
992 auto callee = CreatePeerConnection();
993 ASSERT_TRUE(caller->AddAudioTrack(kTrackLabel, {kStreamLabel}));
994
995 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
996
997 const auto& track_events = callee->observer()->add_track_events_;
998 ASSERT_EQ(1u, track_events.size());
999 const auto& event = track_events[0];
1000 ASSERT_EQ(1u, event.streams.size());
1001 auto stream = event.streams[0];
1002 EXPECT_EQ(kStreamLabel, stream->label());
1003 EXPECT_THAT(track_events[0].snapshotted_stream_tracks.at(stream),
1004 ElementsAre(event.receiver->track()));
1005 EXPECT_EQ(event.receiver->streams(), track_events[0].streams);
1006}
1007
1008// Test that setting a remote offer with two tracks that share the same stream
1009// fires off two OnAddTrack events, both with the same stream that has both
1010// tracks present at the time of firing. This is to ensure that track events are
1011// not fired until SetRemoteDescription has finished processing all the media
1012// sections.
1013TEST_F(PeerConnectionJsepTest,
1014 SetRemoteOfferWithTwoTracksSameStreamFiresOnAddTrack) {
1015 const std::string kTrack1Label = "audio_track1";
1016 const std::string kTrack2Label = "audio_track2";
1017 const std::string kSharedStreamLabel = "stream";
1018
1019 auto caller = CreatePeerConnection();
1020 auto callee = CreatePeerConnection();
1021 ASSERT_TRUE(caller->AddAudioTrack(kTrack1Label, {kSharedStreamLabel}));
1022 ASSERT_TRUE(caller->AddAudioTrack(kTrack2Label, {kSharedStreamLabel}));
1023
1024 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1025
1026 const auto& track_events = callee->observer()->add_track_events_;
1027 ASSERT_EQ(2u, track_events.size());
1028 const auto& event1 = track_events[0];
1029 const auto& event2 = track_events[1];
1030 ASSERT_EQ(1u, event1.streams.size());
1031 auto stream = event1.streams[0];
1032 ASSERT_THAT(event2.streams, ElementsAre(stream));
1033 auto track1 = event1.receiver->track();
1034 auto track2 = event2.receiver->track();
1035 EXPECT_THAT(event1.snapshotted_stream_tracks.at(stream),
1036 UnorderedElementsAre(track1, track2));
1037 EXPECT_THAT(event2.snapshotted_stream_tracks.at(stream),
1038 UnorderedElementsAre(track1, track2));
1039}
1040
1041// TODO(bugs.webrtc.org/7932): Also test multi-stream case.
1042
Steve Antondcc3c022017-12-22 16:02:54 -08001043} // namespace webrtc