1/* 2 * libjingle 3 * Copyright 2012, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <string> 29#include <vector> 30 31#include "talk/app/webrtc/audiotrack.h" 32#include "talk/app/webrtc/mediastream.h" 33#include "talk/app/webrtc/mediastreamsignaling.h" 34#include "talk/app/webrtc/sctputils.h" 35#include "talk/app/webrtc/streamcollection.h" 36#include "talk/app/webrtc/test/fakeconstraints.h" 37#include "talk/app/webrtc/test/fakedatachannelprovider.h" 38#include "talk/app/webrtc/videotrack.h" 39#include "talk/media/base/fakemediaengine.h" 40#include "talk/media/devices/fakedevicemanager.h" 41#include "talk/p2p/base/constants.h" 42#include "talk/p2p/base/sessiondescription.h" 43#include "talk/session/media/channelmanager.h" 44#include "webrtc/base/gunit.h" 45#include "webrtc/base/scoped_ptr.h" 46#include "webrtc/base/stringutils.h" 47#include "webrtc/base/thread.h" 48 49static const char kStreams[][8] = {"stream1", "stream2"}; 50static const char kAudioTracks[][32] = {"audiotrack0", "audiotrack1"}; 51static const char kVideoTracks[][32] = {"videotrack0", "videotrack1"}; 52 53using webrtc::AudioTrack; 54using webrtc::AudioTrackInterface; 55using webrtc::AudioTrackVector; 56using webrtc::VideoTrack; 57using webrtc::VideoTrackInterface; 58using webrtc::VideoTrackVector; 59using webrtc::DataChannelInterface; 60using webrtc::FakeConstraints; 61using webrtc::IceCandidateInterface; 62using webrtc::MediaConstraintsInterface; 63using webrtc::MediaStreamInterface; 64using webrtc::MediaStreamTrackInterface; 65using webrtc::PeerConnectionInterface; 66using webrtc::SdpParseError; 67using webrtc::SessionDescriptionInterface; 68using webrtc::StreamCollection; 69using webrtc::StreamCollectionInterface; 70 71typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; 72 73// Reference SDP with a MediaStream with label "stream1" and audio track with 74// id "audio_1" and a video track with id "video_1; 75static const char kSdpStringWithStream1[] = 76 "v=0\r\n" 77 "o=- 0 0 IN IP4 127.0.0.1\r\n" 78 "s=-\r\n" 79 "t=0 0\r\n" 80 "m=audio 1 RTP/AVPF 103\r\n" 81 "a=mid:audio\r\n" 82 "a=rtpmap:103 ISAC/16000\r\n" 83 "a=ssrc:1 cname:stream1\r\n" 84 "a=ssrc:1 mslabel:stream1\r\n" 85 "a=ssrc:1 label:audiotrack0\r\n" 86 "m=video 1 RTP/AVPF 120\r\n" 87 "a=mid:video\r\n" 88 "a=rtpmap:120 VP8/90000\r\n" 89 "a=ssrc:2 cname:stream1\r\n" 90 "a=ssrc:2 mslabel:stream1\r\n" 91 "a=ssrc:2 label:videotrack0\r\n"; 92 93// Reference SDP with two MediaStreams with label "stream1" and "stream2. Each 94// MediaStreams have one audio track and one video track. 95// This uses MSID. 96static const char kSdpStringWith2Stream[] = 97 "v=0\r\n" 98 "o=- 0 0 IN IP4 127.0.0.1\r\n" 99 "s=-\r\n" 100 "t=0 0\r\n" 101 "a=msid-semantic: WMS stream1 stream2\r\n" 102 "m=audio 1 RTP/AVPF 103\r\n" 103 "a=mid:audio\r\n" 104 "a=rtpmap:103 ISAC/16000\r\n" 105 "a=ssrc:1 cname:stream1\r\n" 106 "a=ssrc:1 msid:stream1 audiotrack0\r\n" 107 "a=ssrc:3 cname:stream2\r\n" 108 "a=ssrc:3 msid:stream2 audiotrack1\r\n" 109 "m=video 1 RTP/AVPF 120\r\n" 110 "a=mid:video\r\n" 111 "a=rtpmap:120 VP8/0\r\n" 112 "a=ssrc:2 cname:stream1\r\n" 113 "a=ssrc:2 msid:stream1 videotrack0\r\n" 114 "a=ssrc:4 cname:stream2\r\n" 115 "a=ssrc:4 msid:stream2 videotrack1\r\n"; 116 117// Reference SDP without MediaStreams. Msid is not supported. 118static const char kSdpStringWithoutStreams[] = 119 "v=0\r\n" 120 "o=- 0 0 IN IP4 127.0.0.1\r\n" 121 "s=-\r\n" 122 "t=0 0\r\n" 123 "m=audio 1 RTP/AVPF 103\r\n" 124 "a=mid:audio\r\n" 125 "a=rtpmap:103 ISAC/16000\r\n" 126 "m=video 1 RTP/AVPF 120\r\n" 127 "a=mid:video\r\n" 128 "a=rtpmap:120 VP8/90000\r\n"; 129 130// Reference SDP without MediaStreams. Msid is supported. 131static const char kSdpStringWithMsidWithoutStreams[] = 132 "v=0\r\n" 133 "o=- 0 0 IN IP4 127.0.0.1\r\n" 134 "s=-\r\n" 135 "t=0 0\r\n" 136 "a=msid-semantic: WMS\r\n" 137 "m=audio 1 RTP/AVPF 103\r\n" 138 "a=mid:audio\r\n" 139 "a=rtpmap:103 ISAC/16000\r\n" 140 "m=video 1 RTP/AVPF 120\r\n" 141 "a=mid:video\r\n" 142 "a=rtpmap:120 VP8/90000\r\n"; 143 144// Reference SDP without MediaStreams and audio only. 145static const char kSdpStringWithoutStreamsAudioOnly[] = 146 "v=0\r\n" 147 "o=- 0 0 IN IP4 127.0.0.1\r\n" 148 "s=-\r\n" 149 "t=0 0\r\n" 150 "m=audio 1 RTP/AVPF 103\r\n" 151 "a=mid:audio\r\n" 152 "a=rtpmap:103 ISAC/16000\r\n"; 153 154// Reference SENDONLY SDP without MediaStreams. Msid is not supported. 155static const char kSdpStringSendOnlyWithWithoutStreams[] = 156 "v=0\r\n" 157 "o=- 0 0 IN IP4 127.0.0.1\r\n" 158 "s=-\r\n" 159 "t=0 0\r\n" 160 "m=audio 1 RTP/AVPF 103\r\n" 161 "a=mid:audio\r\n" 162 "a=sendonly" 163 "a=rtpmap:103 ISAC/16000\r\n" 164 "m=video 1 RTP/AVPF 120\r\n" 165 "a=mid:video\r\n" 166 "a=sendonly" 167 "a=rtpmap:120 VP8/90000\r\n"; 168 169static const char kSdpStringInit[] = 170 "v=0\r\n" 171 "o=- 0 0 IN IP4 127.0.0.1\r\n" 172 "s=-\r\n" 173 "t=0 0\r\n" 174 "a=msid-semantic: WMS\r\n"; 175 176static const char kSdpStringAudio[] = 177 "m=audio 1 RTP/AVPF 103\r\n" 178 "a=mid:audio\r\n" 179 "a=rtpmap:103 ISAC/16000\r\n"; 180 181static const char kSdpStringVideo[] = 182 "m=video 1 RTP/AVPF 120\r\n" 183 "a=mid:video\r\n" 184 "a=rtpmap:120 VP8/90000\r\n"; 185 186static const char kSdpStringMs1Audio0[] = 187 "a=ssrc:1 cname:stream1\r\n" 188 "a=ssrc:1 msid:stream1 audiotrack0\r\n"; 189 190static const char kSdpStringMs1Video0[] = 191 "a=ssrc:2 cname:stream1\r\n" 192 "a=ssrc:2 msid:stream1 videotrack0\r\n"; 193 194static const char kSdpStringMs1Audio1[] = 195 "a=ssrc:3 cname:stream1\r\n" 196 "a=ssrc:3 msid:stream1 audiotrack1\r\n"; 197 198static const char kSdpStringMs1Video1[] = 199 "a=ssrc:4 cname:stream1\r\n" 200 "a=ssrc:4 msid:stream1 videotrack1\r\n"; 201 202// Verifies that |options| contain all tracks in |collection| and that 203// the |options| has set the the has_audio and has_video flags correct. 204static void VerifyMediaOptions(StreamCollectionInterface* collection, 205 const cricket::MediaSessionOptions& options) { 206 if (!collection) { 207 return; 208 } 209 210 size_t stream_index = 0; 211 for (size_t i = 0; i < collection->count(); ++i) { 212 MediaStreamInterface* stream = collection->at(i); 213 AudioTrackVector audio_tracks = stream->GetAudioTracks(); 214 ASSERT_GE(options.streams.size(), stream_index + audio_tracks.size()); 215 for (size_t j = 0; j < audio_tracks.size(); ++j) { 216 webrtc::AudioTrackInterface* audio = audio_tracks[j]; 217 EXPECT_EQ(options.streams[stream_index].sync_label, stream->label()); 218 EXPECT_EQ(options.streams[stream_index++].id, audio->id()); 219 EXPECT_TRUE(options.has_audio); 220 } 221 VideoTrackVector video_tracks = stream->GetVideoTracks(); 222 ASSERT_GE(options.streams.size(), stream_index + video_tracks.size()); 223 for (size_t j = 0; j < video_tracks.size(); ++j) { 224 webrtc::VideoTrackInterface* video = video_tracks[j]; 225 EXPECT_EQ(options.streams[stream_index].sync_label, stream->label()); 226 EXPECT_EQ(options.streams[stream_index++].id, video->id()); 227 EXPECT_TRUE(options.has_video); 228 } 229 } 230} 231 232static bool CompareStreamCollections(StreamCollectionInterface* s1, 233 StreamCollectionInterface* s2) { 234 if (s1 == NULL || s2 == NULL || s1->count() != s2->count()) 235 return false; 236 237 for (size_t i = 0; i != s1->count(); ++i) { 238 if (s1->at(i)->label() != s2->at(i)->label()) 239 return false; 240 webrtc::AudioTrackVector audio_tracks1 = s1->at(i)->GetAudioTracks(); 241 webrtc::AudioTrackVector audio_tracks2 = s2->at(i)->GetAudioTracks(); 242 webrtc::VideoTrackVector video_tracks1 = s1->at(i)->GetVideoTracks(); 243 webrtc::VideoTrackVector video_tracks2 = s2->at(i)->GetVideoTracks(); 244 245 if (audio_tracks1.size() != audio_tracks2.size()) 246 return false; 247 for (size_t j = 0; j != audio_tracks1.size(); ++j) { 248 if (audio_tracks1[j]->id() != audio_tracks2[j]->id()) 249 return false; 250 } 251 if (video_tracks1.size() != video_tracks2.size()) 252 return false; 253 for (size_t j = 0; j != video_tracks1.size(); ++j) { 254 if (video_tracks1[j]->id() != video_tracks2[j]->id()) 255 return false; 256 } 257 } 258 return true; 259} 260 261class FakeDataChannelFactory : public webrtc::DataChannelFactory { 262 public: 263 FakeDataChannelFactory(FakeDataChannelProvider* provider, 264 cricket::DataChannelType dct, 265 webrtc::MediaStreamSignaling* media_stream_signaling) 266 : provider_(provider), 267 type_(dct), 268 media_stream_signaling_(media_stream_signaling) {} 269 270 virtual rtc::scoped_refptr<webrtc::DataChannel> CreateDataChannel( 271 const std::string& label, 272 const webrtc::InternalDataChannelInit* config) { 273 last_init_ = *config; 274 rtc::scoped_refptr<webrtc::DataChannel> data_channel = 275 webrtc::DataChannel::Create(provider_, type_, label, *config); 276 media_stream_signaling_->AddDataChannel(data_channel); 277 return data_channel; 278 } 279 280 const webrtc::InternalDataChannelInit& last_init() const { 281 return last_init_; 282 } 283 284 private: 285 FakeDataChannelProvider* provider_; 286 cricket::DataChannelType type_; 287 webrtc::MediaStreamSignaling* media_stream_signaling_; 288 webrtc::InternalDataChannelInit last_init_; 289}; 290 291class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver { 292 public: 293 MockSignalingObserver() 294 : remote_media_streams_(StreamCollection::Create()) { 295 } 296 297 virtual ~MockSignalingObserver() { 298 } 299 300 // New remote stream have been discovered. 301 virtual void OnAddRemoteStream(MediaStreamInterface* remote_stream) { 302 remote_media_streams_->AddStream(remote_stream); 303 } 304 305 // Remote stream is no longer available. 306 virtual void OnRemoveRemoteStream(MediaStreamInterface* remote_stream) { 307 remote_media_streams_->RemoveStream(remote_stream); 308 } 309 310 virtual void OnAddDataChannel(DataChannelInterface* data_channel) { 311 } 312 313 virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream, 314 AudioTrackInterface* audio_track, 315 uint32 ssrc) { 316 AddTrack(&local_audio_tracks_, stream, audio_track, ssrc); 317 } 318 319 virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream, 320 VideoTrackInterface* video_track, 321 uint32 ssrc) { 322 AddTrack(&local_video_tracks_, stream, video_track, ssrc); 323 } 324 325 virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream, 326 AudioTrackInterface* audio_track, 327 uint32 ssrc) { 328 RemoveTrack(&local_audio_tracks_, stream, audio_track); 329 } 330 331 virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream, 332 VideoTrackInterface* video_track) { 333 RemoveTrack(&local_video_tracks_, stream, video_track); 334 } 335 336 virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream, 337 AudioTrackInterface* audio_track, 338 uint32 ssrc) { 339 AddTrack(&remote_audio_tracks_, stream, audio_track, ssrc); 340 } 341 342 virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream, 343 VideoTrackInterface* video_track, 344 uint32 ssrc) { 345 AddTrack(&remote_video_tracks_, stream, video_track, ssrc); 346 } 347 348 virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream, 349 AudioTrackInterface* audio_track) { 350 RemoveTrack(&remote_audio_tracks_, stream, audio_track); 351 } 352 353 virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream, 354 VideoTrackInterface* video_track) { 355 RemoveTrack(&remote_video_tracks_, stream, video_track); 356 } 357 358 virtual void OnRemoveLocalStream(MediaStreamInterface* stream) { 359 } 360 361 MediaStreamInterface* RemoteStream(const std::string& label) { 362 return remote_media_streams_->find(label); 363 } 364 365 StreamCollectionInterface* remote_streams() const { 366 return remote_media_streams_; 367 } 368 369 size_t NumberOfRemoteAudioTracks() { return remote_audio_tracks_.size(); } 370 371 void VerifyRemoteAudioTrack(const std::string& stream_label, 372 const std::string& track_id, 373 uint32 ssrc) { 374 VerifyTrack(remote_audio_tracks_, stream_label, track_id, ssrc); 375 } 376 377 size_t NumberOfRemoteVideoTracks() { return remote_video_tracks_.size(); } 378 379 void VerifyRemoteVideoTrack(const std::string& stream_label, 380 const std::string& track_id, 381 uint32 ssrc) { 382 VerifyTrack(remote_video_tracks_, stream_label, track_id, ssrc); 383 } 384 385 size_t NumberOfLocalAudioTracks() { return local_audio_tracks_.size(); } 386 void VerifyLocalAudioTrack(const std::string& stream_label, 387 const std::string& track_id, 388 uint32 ssrc) { 389 VerifyTrack(local_audio_tracks_, stream_label, track_id, ssrc); 390 } 391 392 size_t NumberOfLocalVideoTracks() { return local_video_tracks_.size(); } 393 394 void VerifyLocalVideoTrack(const std::string& stream_label, 395 const std::string& track_id, 396 uint32 ssrc) { 397 VerifyTrack(local_video_tracks_, stream_label, track_id, ssrc); 398 } 399 400 private: 401 struct TrackInfo { 402 TrackInfo() {} 403 TrackInfo(const std::string& stream_label, const std::string track_id, 404 uint32 ssrc) 405 : stream_label(stream_label), 406 track_id(track_id), 407 ssrc(ssrc) { 408 } 409 std::string stream_label; 410 std::string track_id; 411 uint32 ssrc; 412 }; 413 typedef std::vector<TrackInfo> TrackInfos; 414 415 void AddTrack(TrackInfos* track_infos, MediaStreamInterface* stream, 416 MediaStreamTrackInterface* track, 417 uint32 ssrc) { 418 (*track_infos).push_back(TrackInfo(stream->label(), track->id(), 419 ssrc)); 420 } 421 422 void RemoveTrack(TrackInfos* track_infos, MediaStreamInterface* stream, 423 MediaStreamTrackInterface* track) { 424 for (TrackInfos::iterator it = track_infos->begin(); 425 it != track_infos->end(); ++it) { 426 if (it->stream_label == stream->label() && it->track_id == track->id()) { 427 track_infos->erase(it); 428 return; 429 } 430 } 431 ADD_FAILURE(); 432 } 433 434 const TrackInfo* FindTrackInfo(const TrackInfos& infos, 435 const std::string& stream_label, 436 const std::string track_id) const { 437 for (TrackInfos::const_iterator it = infos.begin(); 438 it != infos.end(); ++it) { 439 if (it->stream_label == stream_label && it->track_id == track_id) 440 return &*it; 441 } 442 return NULL; 443 } 444 445 446 void VerifyTrack(const TrackInfos& track_infos, 447 const std::string& stream_label, 448 const std::string& track_id, 449 uint32 ssrc) { 450 const TrackInfo* track_info = FindTrackInfo(track_infos, 451 stream_label, 452 track_id); 453 ASSERT_TRUE(track_info != NULL); 454 EXPECT_EQ(ssrc, track_info->ssrc); 455 } 456 457 TrackInfos remote_audio_tracks_; 458 TrackInfos remote_video_tracks_; 459 TrackInfos local_audio_tracks_; 460 TrackInfos local_video_tracks_; 461 462 rtc::scoped_refptr<StreamCollection> remote_media_streams_; 463}; 464 465class MediaStreamSignalingForTest : public webrtc::MediaStreamSignaling { 466 public: 467 MediaStreamSignalingForTest(MockSignalingObserver* observer, 468 cricket::ChannelManager* channel_manager) 469 : webrtc::MediaStreamSignaling(rtc::Thread::Current(), observer, 470 channel_manager) { 471 }; 472 473 using webrtc::MediaStreamSignaling::GetOptionsForOffer; 474 using webrtc::MediaStreamSignaling::GetOptionsForAnswer; 475 using webrtc::MediaStreamSignaling::OnRemoteDescriptionChanged; 476 using webrtc::MediaStreamSignaling::remote_streams; 477}; 478 479class MediaStreamSignalingTest: public testing::Test { 480 protected: 481 virtual void SetUp() { 482 observer_.reset(new MockSignalingObserver()); 483 channel_manager_.reset( 484 new cricket::ChannelManager(new cricket::FakeMediaEngine(), 485 new cricket::FakeDeviceManager(), 486 rtc::Thread::Current())); 487 signaling_.reset(new MediaStreamSignalingForTest(observer_.get(), 488 channel_manager_.get())); 489 data_channel_provider_.reset(new FakeDataChannelProvider()); 490 } 491 492 // Create a collection of streams. 493 // CreateStreamCollection(1) creates a collection that 494 // correspond to kSdpString1. 495 // CreateStreamCollection(2) correspond to kSdpString2. 496 rtc::scoped_refptr<StreamCollection> 497 CreateStreamCollection(int number_of_streams) { 498 rtc::scoped_refptr<StreamCollection> local_collection( 499 StreamCollection::Create()); 500 501 for (int i = 0; i < number_of_streams; ++i) { 502 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream( 503 webrtc::MediaStream::Create(kStreams[i])); 504 505 // Add a local audio track. 506 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track( 507 webrtc::AudioTrack::Create(kAudioTracks[i], NULL)); 508 stream->AddTrack(audio_track); 509 510 // Add a local video track. 511 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track( 512 webrtc::VideoTrack::Create(kVideoTracks[i], NULL)); 513 stream->AddTrack(video_track); 514 515 local_collection->AddStream(stream); 516 } 517 return local_collection; 518 } 519 520 // This functions Creates a MediaStream with label kStreams[0] and 521 // |number_of_audio_tracks| and |number_of_video_tracks| tracks and the 522 // corresponding SessionDescriptionInterface. The SessionDescriptionInterface 523 // is returned in |desc| and the MediaStream is stored in 524 // |reference_collection_| 525 void CreateSessionDescriptionAndReference( 526 size_t number_of_audio_tracks, 527 size_t number_of_video_tracks, 528 SessionDescriptionInterface** desc) { 529 ASSERT_TRUE(desc != NULL); 530 ASSERT_LE(number_of_audio_tracks, 2u); 531 ASSERT_LE(number_of_video_tracks, 2u); 532 533 reference_collection_ = StreamCollection::Create(); 534 std::string sdp_ms1 = std::string(kSdpStringInit); 535 536 std::string mediastream_label = kStreams[0]; 537 538 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream( 539 webrtc::MediaStream::Create(mediastream_label)); 540 reference_collection_->AddStream(stream); 541 542 if (number_of_audio_tracks > 0) { 543 sdp_ms1 += std::string(kSdpStringAudio); 544 sdp_ms1 += std::string(kSdpStringMs1Audio0); 545 AddAudioTrack(kAudioTracks[0], stream); 546 } 547 if (number_of_audio_tracks > 1) { 548 sdp_ms1 += kSdpStringMs1Audio1; 549 AddAudioTrack(kAudioTracks[1], stream); 550 } 551 552 if (number_of_video_tracks > 0) { 553 sdp_ms1 += std::string(kSdpStringVideo); 554 sdp_ms1 += std::string(kSdpStringMs1Video0); 555 AddVideoTrack(kVideoTracks[0], stream); 556 } 557 if (number_of_video_tracks > 1) { 558 sdp_ms1 += kSdpStringMs1Video1; 559 AddVideoTrack(kVideoTracks[1], stream); 560 } 561 562 *desc = webrtc::CreateSessionDescription( 563 SessionDescriptionInterface::kOffer, sdp_ms1, NULL); 564 } 565 566 void AddAudioTrack(const std::string& track_id, 567 MediaStreamInterface* stream) { 568 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track( 569 webrtc::AudioTrack::Create(track_id, NULL)); 570 ASSERT_TRUE(stream->AddTrack(audio_track)); 571 } 572 573 void AddVideoTrack(const std::string& track_id, 574 MediaStreamInterface* stream) { 575 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track( 576 webrtc::VideoTrack::Create(track_id, NULL)); 577 ASSERT_TRUE(stream->AddTrack(video_track)); 578 } 579 580 rtc::scoped_refptr<webrtc::DataChannel> AddDataChannel( 581 cricket::DataChannelType type, const std::string& label, int id) { 582 webrtc::InternalDataChannelInit config; 583 config.id = id; 584 rtc::scoped_refptr<webrtc::DataChannel> data_channel( 585 webrtc::DataChannel::Create( 586 data_channel_provider_.get(), type, label, config)); 587 EXPECT_TRUE(data_channel.get() != NULL); 588 EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get())); 589 return data_channel; 590 } 591 592 // ChannelManager is used by VideoSource, so it should be released after all 593 // the video tracks. Put it as the first private variable should ensure that. 594 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_; 595 rtc::scoped_refptr<StreamCollection> reference_collection_; 596 rtc::scoped_ptr<MockSignalingObserver> observer_; 597 rtc::scoped_ptr<MediaStreamSignalingForTest> signaling_; 598 rtc::scoped_ptr<FakeDataChannelProvider> data_channel_provider_; 599}; 600 601TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidAudioOption) { 602 RTCOfferAnswerOptions rtc_options; 603 rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1; 604 605 cricket::MediaSessionOptions options; 606 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options)); 607 608 rtc_options.offer_to_receive_audio = 609 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1; 610 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options)); 611} 612 613 614TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidVideoOption) { 615 RTCOfferAnswerOptions rtc_options; 616 rtc_options.offer_to_receive_video = 617 RTCOfferAnswerOptions::kUndefined - 1; 618 619 cricket::MediaSessionOptions options; 620 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options)); 621 622 rtc_options.offer_to_receive_video = 623 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1; 624 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options)); 625} 626 627// Test that a MediaSessionOptions is created for an offer if 628// OfferToReceiveAudio and OfferToReceiveVideo options are set but no 629// MediaStreams are sent. 630TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudioVideo) { 631 RTCOfferAnswerOptions rtc_options; 632 rtc_options.offer_to_receive_audio = 1; 633 rtc_options.offer_to_receive_video = 1; 634 635 cricket::MediaSessionOptions options; 636 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 637 EXPECT_TRUE(options.has_audio); 638 EXPECT_TRUE(options.has_video); 639 EXPECT_TRUE(options.bundle_enabled); 640} 641 642// Test that a correct MediaSessionOptions is created for an offer if 643// OfferToReceiveAudio is set but no MediaStreams are sent. 644TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudio) { 645 RTCOfferAnswerOptions rtc_options; 646 rtc_options.offer_to_receive_audio = 1; 647 648 cricket::MediaSessionOptions options; 649 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 650 EXPECT_TRUE(options.has_audio); 651 EXPECT_FALSE(options.has_video); 652 EXPECT_TRUE(options.bundle_enabled); 653} 654 655// Test that a correct MediaSessionOptions is created for an offer if 656// the default OfferOptons is used or MediaStreams are sent. 657TEST_F(MediaStreamSignalingTest, GetDefaultMediaSessionOptionsForOffer) { 658 RTCOfferAnswerOptions rtc_options; 659 660 cricket::MediaSessionOptions options; 661 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 662 EXPECT_FALSE(options.has_audio); 663 EXPECT_FALSE(options.has_video); 664 EXPECT_FALSE(options.bundle_enabled); 665 EXPECT_TRUE(options.vad_enabled); 666 EXPECT_FALSE(options.transport_options.ice_restart); 667} 668 669// Test that a correct MediaSessionOptions is created for an offer if 670// OfferToReceiveVideo is set but no MediaStreams are sent. 671TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithVideo) { 672 RTCOfferAnswerOptions rtc_options; 673 rtc_options.offer_to_receive_audio = 0; 674 rtc_options.offer_to_receive_video = 1; 675 676 cricket::MediaSessionOptions options; 677 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 678 EXPECT_FALSE(options.has_audio); 679 EXPECT_TRUE(options.has_video); 680 EXPECT_TRUE(options.bundle_enabled); 681} 682 683// Test that a correct MediaSessionOptions is created for an offer if 684// UseRtpMux is set to false. 685TEST_F(MediaStreamSignalingTest, 686 GetMediaSessionOptionsForOfferWithBundleDisabled) { 687 RTCOfferAnswerOptions rtc_options; 688 rtc_options.offer_to_receive_audio = 1; 689 rtc_options.offer_to_receive_video = 1; 690 rtc_options.use_rtp_mux = false; 691 692 cricket::MediaSessionOptions options; 693 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 694 EXPECT_TRUE(options.has_audio); 695 EXPECT_TRUE(options.has_video); 696 EXPECT_FALSE(options.bundle_enabled); 697} 698 699// Test that a correct MediaSessionOptions is created to restart ice if 700// IceRestart is set. It also tests that subsequent MediaSessionOptions don't 701// have |transport_options.ice_restart| set. 702TEST_F(MediaStreamSignalingTest, 703 GetMediaSessionOptionsForOfferWithIceRestart) { 704 RTCOfferAnswerOptions rtc_options; 705 rtc_options.ice_restart = true; 706 707 cricket::MediaSessionOptions options; 708 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 709 EXPECT_TRUE(options.transport_options.ice_restart); 710 711 rtc_options = RTCOfferAnswerOptions(); 712 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 713 EXPECT_FALSE(options.transport_options.ice_restart); 714} 715 716// Test that a correct MediaSessionOptions are created for an offer if 717// a MediaStream is sent and later updated with a new track. 718// MediaConstraints are not used. 719TEST_F(MediaStreamSignalingTest, AddTrackToLocalMediaStream) { 720 RTCOfferAnswerOptions rtc_options; 721 rtc::scoped_refptr<StreamCollection> local_streams( 722 CreateStreamCollection(1)); 723 MediaStreamInterface* local_stream = local_streams->at(0); 724 EXPECT_TRUE(signaling_->AddLocalStream(local_stream)); 725 cricket::MediaSessionOptions options; 726 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 727 VerifyMediaOptions(local_streams, options); 728 729 cricket::MediaSessionOptions updated_options; 730 local_stream->AddTrack(AudioTrack::Create(kAudioTracks[1], NULL)); 731 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options)); 732 VerifyMediaOptions(local_streams, options); 733} 734 735// Test that the MediaConstraints in an answer don't affect if audio and video 736// is offered in an offer but that if kOfferToReceiveAudio or 737// kOfferToReceiveVideo constraints are true in an offer, the media type will be 738// included in subsequent answers. 739TEST_F(MediaStreamSignalingTest, MediaConstraintsInAnswer) { 740 FakeConstraints answer_c; 741 answer_c.SetMandatoryReceiveAudio(true); 742 answer_c.SetMandatoryReceiveVideo(true); 743 744 cricket::MediaSessionOptions answer_options; 745 EXPECT_TRUE(signaling_->GetOptionsForAnswer(&answer_c, &answer_options)); 746 EXPECT_TRUE(answer_options.has_audio); 747 EXPECT_TRUE(answer_options.has_video); 748 749 RTCOfferAnswerOptions rtc_offer_optoins; 750 751 cricket::MediaSessionOptions offer_options; 752 EXPECT_TRUE( 753 signaling_->GetOptionsForOffer(rtc_offer_optoins, &offer_options)); 754 EXPECT_FALSE(offer_options.has_audio); 755 EXPECT_FALSE(offer_options.has_video); 756 757 RTCOfferAnswerOptions updated_rtc_offer_optoins; 758 updated_rtc_offer_optoins.offer_to_receive_audio = 1; 759 updated_rtc_offer_optoins.offer_to_receive_video = 1; 760 761 cricket::MediaSessionOptions updated_offer_options; 762 EXPECT_TRUE(signaling_->GetOptionsForOffer(updated_rtc_offer_optoins, 763 &updated_offer_options)); 764 EXPECT_TRUE(updated_offer_options.has_audio); 765 EXPECT_TRUE(updated_offer_options.has_video); 766 767 // Since an offer has been created with both audio and video, subsequent 768 // offers and answers should contain both audio and video. 769 // Answers will only contain the media types that exist in the offer 770 // regardless of the value of |updated_answer_options.has_audio| and 771 // |updated_answer_options.has_video|. 772 FakeConstraints updated_answer_c; 773 answer_c.SetMandatoryReceiveAudio(false); 774 answer_c.SetMandatoryReceiveVideo(false); 775 776 cricket::MediaSessionOptions updated_answer_options; 777 EXPECT_TRUE(signaling_->GetOptionsForAnswer(&updated_answer_c, 778 &updated_answer_options)); 779 EXPECT_TRUE(updated_answer_options.has_audio); 780 EXPECT_TRUE(updated_answer_options.has_video); 781 782 RTCOfferAnswerOptions default_rtc_options; 783 EXPECT_TRUE(signaling_->GetOptionsForOffer(default_rtc_options, 784 &updated_offer_options)); 785 // By default, |has_audio| or |has_video| are false if there is no media 786 // track. 787 EXPECT_FALSE(updated_offer_options.has_audio); 788 EXPECT_FALSE(updated_offer_options.has_video); 789} 790 791// This test verifies that the remote MediaStreams corresponding to a received 792// SDP string is created. In this test the two separate MediaStreams are 793// signaled. 794TEST_F(MediaStreamSignalingTest, UpdateRemoteStreams) { 795 rtc::scoped_ptr<SessionDescriptionInterface> desc( 796 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 797 kSdpStringWithStream1, NULL)); 798 EXPECT_TRUE(desc != NULL); 799 signaling_->OnRemoteDescriptionChanged(desc.get()); 800 801 rtc::scoped_refptr<StreamCollection> reference( 802 CreateStreamCollection(1)); 803 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(), 804 reference.get())); 805 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(), 806 reference.get())); 807 EXPECT_EQ(1u, observer_->NumberOfRemoteAudioTracks()); 808 observer_->VerifyRemoteAudioTrack(kStreams[0], kAudioTracks[0], 1); 809 EXPECT_EQ(1u, observer_->NumberOfRemoteVideoTracks()); 810 observer_->VerifyRemoteVideoTrack(kStreams[0], kVideoTracks[0], 2); 811 ASSERT_EQ(1u, observer_->remote_streams()->count()); 812 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0); 813 EXPECT_TRUE(remote_stream->GetVideoTracks()[0]->GetSource() != NULL); 814 815 // Create a session description based on another SDP with another 816 // MediaStream. 817 rtc::scoped_ptr<SessionDescriptionInterface> update_desc( 818 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 819 kSdpStringWith2Stream, NULL)); 820 EXPECT_TRUE(update_desc != NULL); 821 signaling_->OnRemoteDescriptionChanged(update_desc.get()); 822 823 rtc::scoped_refptr<StreamCollection> reference2( 824 CreateStreamCollection(2)); 825 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(), 826 reference2.get())); 827 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(), 828 reference2.get())); 829 830 EXPECT_EQ(2u, observer_->NumberOfRemoteAudioTracks()); 831 observer_->VerifyRemoteAudioTrack(kStreams[0], kAudioTracks[0], 1); 832 observer_->VerifyRemoteAudioTrack(kStreams[1], kAudioTracks[1], 3); 833 EXPECT_EQ(2u, observer_->NumberOfRemoteVideoTracks()); 834 observer_->VerifyRemoteVideoTrack(kStreams[0], kVideoTracks[0], 2); 835 observer_->VerifyRemoteVideoTrack(kStreams[1], kVideoTracks[1], 4); 836} 837 838// This test verifies that the remote MediaStreams corresponding to a received 839// SDP string is created. In this test the same remote MediaStream is signaled 840// but MediaStream tracks are added and removed. 841TEST_F(MediaStreamSignalingTest, AddRemoveTrackFromExistingRemoteMediaStream) { 842 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1; 843 CreateSessionDescriptionAndReference(1, 1, desc_ms1.use()); 844 signaling_->OnRemoteDescriptionChanged(desc_ms1.get()); 845 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(), 846 reference_collection_)); 847 848 // Add extra audio and video tracks to the same MediaStream. 849 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1_two_tracks; 850 CreateSessionDescriptionAndReference(2, 2, desc_ms1_two_tracks.use()); 851 signaling_->OnRemoteDescriptionChanged(desc_ms1_two_tracks.get()); 852 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(), 853 reference_collection_)); 854 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(), 855 reference_collection_)); 856 857 // Remove the extra audio and video tracks again. 858 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms2; 859 CreateSessionDescriptionAndReference(1, 1, desc_ms2.use()); 860 signaling_->OnRemoteDescriptionChanged(desc_ms2.get()); 861 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(), 862 reference_collection_)); 863 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(), 864 reference_collection_)); 865} 866 867// This test that remote tracks are ended if a 868// local session description is set that rejects the media content type. 869TEST_F(MediaStreamSignalingTest, RejectMediaContent) { 870 rtc::scoped_ptr<SessionDescriptionInterface> desc( 871 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 872 kSdpStringWithStream1, NULL)); 873 EXPECT_TRUE(desc != NULL); 874 signaling_->OnRemoteDescriptionChanged(desc.get()); 875 876 ASSERT_EQ(1u, observer_->remote_streams()->count()); 877 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0); 878 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size()); 879 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size()); 880 881 rtc::scoped_refptr<webrtc::VideoTrackInterface> remote_video = 882 remote_stream->GetVideoTracks()[0]; 883 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_video->state()); 884 rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_audio = 885 remote_stream->GetAudioTracks()[0]; 886 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state()); 887 888 cricket::ContentInfo* video_info = 889 desc->description()->GetContentByName("video"); 890 ASSERT_TRUE(video_info != NULL); 891 video_info->rejected = true; 892 signaling_->OnLocalDescriptionChanged(desc.get()); 893 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state()); 894 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state()); 895 896 cricket::ContentInfo* audio_info = 897 desc->description()->GetContentByName("audio"); 898 ASSERT_TRUE(audio_info != NULL); 899 audio_info->rejected = true; 900 signaling_->OnLocalDescriptionChanged(desc.get()); 901 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_audio->state()); 902} 903 904// This test that it won't crash if the remote track as been removed outside 905// of MediaStreamSignaling and then MediaStreamSignaling tries to reject 906// this track. 907TEST_F(MediaStreamSignalingTest, RemoveTrackThenRejectMediaContent) { 908 rtc::scoped_ptr<SessionDescriptionInterface> desc( 909 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 910 kSdpStringWithStream1, NULL)); 911 EXPECT_TRUE(desc != NULL); 912 signaling_->OnRemoteDescriptionChanged(desc.get()); 913 914 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0); 915 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]); 916 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]); 917 918 cricket::ContentInfo* video_info = 919 desc->description()->GetContentByName("video"); 920 video_info->rejected = true; 921 signaling_->OnLocalDescriptionChanged(desc.get()); 922 923 cricket::ContentInfo* audio_info = 924 desc->description()->GetContentByName("audio"); 925 audio_info->rejected = true; 926 signaling_->OnLocalDescriptionChanged(desc.get()); 927 928 // No crash is a pass. 929} 930 931// This tests that a default MediaStream is created if a remote session 932// description doesn't contain any streams and no MSID support. 933// It also tests that the default stream is updated if a video m-line is added 934// in a subsequent session description. 935TEST_F(MediaStreamSignalingTest, SdpWithoutMsidCreatesDefaultStream) { 936 rtc::scoped_ptr<SessionDescriptionInterface> desc_audio_only( 937 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 938 kSdpStringWithoutStreamsAudioOnly, 939 NULL)); 940 ASSERT_TRUE(desc_audio_only != NULL); 941 signaling_->OnRemoteDescriptionChanged(desc_audio_only.get()); 942 943 EXPECT_EQ(1u, signaling_->remote_streams()->count()); 944 ASSERT_EQ(1u, observer_->remote_streams()->count()); 945 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0); 946 947 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size()); 948 EXPECT_EQ(0u, remote_stream->GetVideoTracks().size()); 949 EXPECT_EQ("default", remote_stream->label()); 950 951 rtc::scoped_ptr<SessionDescriptionInterface> desc( 952 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 953 kSdpStringWithoutStreams, NULL)); 954 ASSERT_TRUE(desc != NULL); 955 signaling_->OnRemoteDescriptionChanged(desc.get()); 956 EXPECT_EQ(1u, signaling_->remote_streams()->count()); 957 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size()); 958 EXPECT_EQ("defaulta0", remote_stream->GetAudioTracks()[0]->id()); 959 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size()); 960 EXPECT_EQ("defaultv0", remote_stream->GetVideoTracks()[0]->id()); 961 observer_->VerifyRemoteAudioTrack("default", "defaulta0", 0); 962 observer_->VerifyRemoteVideoTrack("default", "defaultv0", 0); 963} 964 965// This tests that a default MediaStream is created if a remote session 966// description doesn't contain any streams and media direction is send only. 967TEST_F(MediaStreamSignalingTest, RecvOnlySdpWithoutMsidCreatesDefaultStream) { 968 rtc::scoped_ptr<SessionDescriptionInterface> desc( 969 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 970 kSdpStringSendOnlyWithWithoutStreams, 971 NULL)); 972 ASSERT_TRUE(desc != NULL); 973 signaling_->OnRemoteDescriptionChanged(desc.get()); 974 975 EXPECT_EQ(1u, signaling_->remote_streams()->count()); 976 ASSERT_EQ(1u, observer_->remote_streams()->count()); 977 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0); 978 979 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size()); 980 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size()); 981 EXPECT_EQ("default", remote_stream->label()); 982} 983 984// This tests that it won't crash when MediaStreamSignaling tries to remove 985// a remote track that as already been removed from the mediastream. 986TEST_F(MediaStreamSignalingTest, RemoveAlreadyGoneRemoteStream) { 987 rtc::scoped_ptr<SessionDescriptionInterface> desc_audio_only( 988 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 989 kSdpStringWithoutStreams, 990 NULL)); 991 ASSERT_TRUE(desc_audio_only != NULL); 992 signaling_->OnRemoteDescriptionChanged(desc_audio_only.get()); 993 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0); 994 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]); 995 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]); 996 997 rtc::scoped_ptr<SessionDescriptionInterface> desc( 998 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 999 kSdpStringWithoutStreams, NULL)); 1000 ASSERT_TRUE(desc != NULL); 1001 signaling_->OnRemoteDescriptionChanged(desc.get()); 1002 1003 // No crash is a pass. 1004} 1005 1006// This tests that a default MediaStream is created if the remote session 1007// description doesn't contain any streams and don't contain an indication if 1008// MSID is supported. 1009TEST_F(MediaStreamSignalingTest, 1010 SdpWithoutMsidAndStreamsCreatesDefaultStream) { 1011 rtc::scoped_ptr<SessionDescriptionInterface> desc( 1012 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 1013 kSdpStringWithoutStreams, 1014 NULL)); 1015 ASSERT_TRUE(desc != NULL); 1016 signaling_->OnRemoteDescriptionChanged(desc.get()); 1017 1018 ASSERT_EQ(1u, observer_->remote_streams()->count()); 1019 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0); 1020 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size()); 1021 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size()); 1022} 1023 1024// This tests that a default MediaStream is not created if the remote session 1025// description doesn't contain any streams but does support MSID. 1026TEST_F(MediaStreamSignalingTest, SdpWitMsidDontCreatesDefaultStream) { 1027 rtc::scoped_ptr<SessionDescriptionInterface> desc_msid_without_streams( 1028 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 1029 kSdpStringWithMsidWithoutStreams, 1030 NULL)); 1031 signaling_->OnRemoteDescriptionChanged(desc_msid_without_streams.get()); 1032 EXPECT_EQ(0u, observer_->remote_streams()->count()); 1033} 1034 1035// This test that a default MediaStream is not created if a remote session 1036// description is updated to not have any MediaStreams. 1037TEST_F(MediaStreamSignalingTest, VerifyDefaultStreamIsNotCreated) { 1038 rtc::scoped_ptr<SessionDescriptionInterface> desc( 1039 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 1040 kSdpStringWithStream1, 1041 NULL)); 1042 ASSERT_TRUE(desc != NULL); 1043 signaling_->OnRemoteDescriptionChanged(desc.get()); 1044 rtc::scoped_refptr<StreamCollection> reference( 1045 CreateStreamCollection(1)); 1046 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(), 1047 reference.get())); 1048 1049 rtc::scoped_ptr<SessionDescriptionInterface> desc_without_streams( 1050 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 1051 kSdpStringWithoutStreams, 1052 NULL)); 1053 signaling_->OnRemoteDescriptionChanged(desc_without_streams.get()); 1054 EXPECT_EQ(0u, observer_->remote_streams()->count()); 1055} 1056 1057// This test that the correct MediaStreamSignalingObserver methods are called 1058// when MediaStreamSignaling::OnLocalDescriptionChanged is called with an 1059// updated local session description. 1060TEST_F(MediaStreamSignalingTest, LocalDescriptionChanged) { 1061 rtc::scoped_ptr<SessionDescriptionInterface> desc_1; 1062 CreateSessionDescriptionAndReference(2, 2, desc_1.use()); 1063 1064 signaling_->AddLocalStream(reference_collection_->at(0)); 1065 signaling_->OnLocalDescriptionChanged(desc_1.get()); 1066 EXPECT_EQ(2u, observer_->NumberOfLocalAudioTracks()); 1067 EXPECT_EQ(2u, observer_->NumberOfLocalVideoTracks()); 1068 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1); 1069 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2); 1070 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[1], 3); 1071 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[1], 4); 1072 1073 // Remove an audio and video track. 1074 rtc::scoped_ptr<SessionDescriptionInterface> desc_2; 1075 CreateSessionDescriptionAndReference(1, 1, desc_2.use()); 1076 signaling_->OnLocalDescriptionChanged(desc_2.get()); 1077 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks()); 1078 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks()); 1079 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1); 1080 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2); 1081} 1082 1083// This test that the correct MediaStreamSignalingObserver methods are called 1084// when MediaStreamSignaling::AddLocalStream is called after 1085// MediaStreamSignaling::OnLocalDescriptionChanged is called. 1086TEST_F(MediaStreamSignalingTest, AddLocalStreamAfterLocalDescriptionChanged) { 1087 rtc::scoped_ptr<SessionDescriptionInterface> desc_1; 1088 CreateSessionDescriptionAndReference(2, 2, desc_1.use()); 1089 1090 signaling_->OnLocalDescriptionChanged(desc_1.get()); 1091 EXPECT_EQ(0u, observer_->NumberOfLocalAudioTracks()); 1092 EXPECT_EQ(0u, observer_->NumberOfLocalVideoTracks()); 1093 1094 signaling_->AddLocalStream(reference_collection_->at(0)); 1095 EXPECT_EQ(2u, observer_->NumberOfLocalAudioTracks()); 1096 EXPECT_EQ(2u, observer_->NumberOfLocalVideoTracks()); 1097 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1); 1098 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2); 1099 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[1], 3); 1100 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[1], 4); 1101} 1102 1103// This test that the correct MediaStreamSignalingObserver methods are called 1104// if the ssrc on a local track is changed when 1105// MediaStreamSignaling::OnLocalDescriptionChanged is called. 1106TEST_F(MediaStreamSignalingTest, ChangeSsrcOnTrackInLocalSessionDescription) { 1107 rtc::scoped_ptr<SessionDescriptionInterface> desc; 1108 CreateSessionDescriptionAndReference(1, 1, desc.use()); 1109 1110 signaling_->AddLocalStream(reference_collection_->at(0)); 1111 signaling_->OnLocalDescriptionChanged(desc.get()); 1112 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks()); 1113 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks()); 1114 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1); 1115 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2); 1116 1117 // Change the ssrc of the audio and video track. 1118 std::string sdp; 1119 desc->ToString(&sdp); 1120 std::string ssrc_org = "a=ssrc:1"; 1121 std::string ssrc_to = "a=ssrc:97"; 1122 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), 1123 ssrc_to.c_str(), ssrc_to.length(), 1124 &sdp); 1125 ssrc_org = "a=ssrc:2"; 1126 ssrc_to = "a=ssrc:98"; 1127 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), 1128 ssrc_to.c_str(), ssrc_to.length(), 1129 &sdp); 1130 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc( 1131 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 1132 sdp, NULL)); 1133 1134 signaling_->OnLocalDescriptionChanged(updated_desc.get()); 1135 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks()); 1136 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks()); 1137 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 97); 1138 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 98); 1139} 1140 1141// This test that the correct MediaStreamSignalingObserver methods are called 1142// if a new session description is set with the same tracks but they are now 1143// sent on a another MediaStream. 1144TEST_F(MediaStreamSignalingTest, SignalSameTracksInSeparateMediaStream) { 1145 rtc::scoped_ptr<SessionDescriptionInterface> desc; 1146 CreateSessionDescriptionAndReference(1, 1, desc.use()); 1147 1148 signaling_->AddLocalStream(reference_collection_->at(0)); 1149 signaling_->OnLocalDescriptionChanged(desc.get()); 1150 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks()); 1151 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks()); 1152 1153 std::string stream_label_0 = kStreams[0]; 1154 observer_->VerifyLocalAudioTrack(stream_label_0, kAudioTracks[0], 1); 1155 observer_->VerifyLocalVideoTrack(stream_label_0, kVideoTracks[0], 2); 1156 1157 // Add a new MediaStream but with the same tracks as in the first stream. 1158 std::string stream_label_1 = kStreams[1]; 1159 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_1( 1160 webrtc::MediaStream::Create(kStreams[1])); 1161 stream_1->AddTrack(reference_collection_->at(0)->GetVideoTracks()[0]); 1162 stream_1->AddTrack(reference_collection_->at(0)->GetAudioTracks()[0]); 1163 signaling_->AddLocalStream(stream_1); 1164 1165 // Replace msid in the original SDP. 1166 std::string sdp; 1167 desc->ToString(&sdp); 1168 rtc::replace_substrs( 1169 kStreams[0], strlen(kStreams[0]), kStreams[1], strlen(kStreams[1]), &sdp); 1170 1171 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc( 1172 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, 1173 sdp, NULL)); 1174 1175 signaling_->OnLocalDescriptionChanged(updated_desc.get()); 1176 observer_->VerifyLocalAudioTrack(kStreams[1], kAudioTracks[0], 1); 1177 observer_->VerifyLocalVideoTrack(kStreams[1], kVideoTracks[0], 2); 1178 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks()); 1179 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks()); 1180} 1181 1182// Verifies that an even SCTP id is allocated for SSL_CLIENT and an odd id for 1183// SSL_SERVER. 1184TEST_F(MediaStreamSignalingTest, SctpIdAllocationBasedOnRole) { 1185 int id; 1186 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &id)); 1187 EXPECT_EQ(1, id); 1188 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &id)); 1189 EXPECT_EQ(0, id); 1190 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &id)); 1191 EXPECT_EQ(3, id); 1192 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &id)); 1193 EXPECT_EQ(2, id); 1194} 1195 1196// Verifies that SCTP ids of existing DataChannels are not reused. 1197TEST_F(MediaStreamSignalingTest, SctpIdAllocationNoReuse) { 1198 int old_id = 1; 1199 AddDataChannel(cricket::DCT_SCTP, "a", old_id); 1200 1201 int new_id; 1202 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &new_id)); 1203 EXPECT_NE(old_id, new_id); 1204 1205 // Creates a DataChannel with id 0. 1206 old_id = 0; 1207 AddDataChannel(cricket::DCT_SCTP, "a", old_id); 1208 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &new_id)); 1209 EXPECT_NE(old_id, new_id); 1210} 1211 1212// Verifies that SCTP ids of removed DataChannels can be reused. 1213TEST_F(MediaStreamSignalingTest, SctpIdReusedForRemovedDataChannel) { 1214 int odd_id = 1; 1215 int even_id = 0; 1216 AddDataChannel(cricket::DCT_SCTP, "a", odd_id); 1217 AddDataChannel(cricket::DCT_SCTP, "a", even_id); 1218 1219 int allocated_id = -1; 1220 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, 1221 &allocated_id)); 1222 EXPECT_EQ(odd_id + 2, allocated_id); 1223 AddDataChannel(cricket::DCT_SCTP, "a", allocated_id); 1224 1225 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, 1226 &allocated_id)); 1227 EXPECT_EQ(even_id + 2, allocated_id); 1228 AddDataChannel(cricket::DCT_SCTP, "a", allocated_id); 1229 1230 signaling_->RemoveSctpDataChannel(odd_id); 1231 signaling_->RemoveSctpDataChannel(even_id); 1232 1233 // Verifies that removed DataChannel ids are reused. 1234 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, 1235 &allocated_id)); 1236 EXPECT_EQ(odd_id, allocated_id); 1237 1238 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, 1239 &allocated_id)); 1240 EXPECT_EQ(even_id, allocated_id); 1241 1242 // Verifies that used higher DataChannel ids are not reused. 1243 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, 1244 &allocated_id)); 1245 EXPECT_NE(odd_id + 2, allocated_id); 1246 1247 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, 1248 &allocated_id)); 1249 EXPECT_NE(even_id + 2, allocated_id); 1250 1251} 1252 1253// Verifies that duplicated label is not allowed for RTP data channel. 1254TEST_F(MediaStreamSignalingTest, RtpDuplicatedLabelNotAllowed) { 1255 AddDataChannel(cricket::DCT_RTP, "a", -1); 1256 1257 webrtc::InternalDataChannelInit config; 1258 rtc::scoped_refptr<webrtc::DataChannel> data_channel = 1259 webrtc::DataChannel::Create( 1260 data_channel_provider_.get(), cricket::DCT_RTP, "a", config); 1261 ASSERT_TRUE(data_channel.get() != NULL); 1262 EXPECT_FALSE(signaling_->AddDataChannel(data_channel.get())); 1263} 1264 1265// Verifies that duplicated label is allowed for SCTP data channel. 1266TEST_F(MediaStreamSignalingTest, SctpDuplicatedLabelAllowed) { 1267 AddDataChannel(cricket::DCT_SCTP, "a", -1); 1268 AddDataChannel(cricket::DCT_SCTP, "a", -1); 1269} 1270 1271// Verifies the correct configuration is used to create DataChannel from an OPEN 1272// message. 1273TEST_F(MediaStreamSignalingTest, CreateDataChannelFromOpenMessage) { 1274 FakeDataChannelFactory fake_factory(data_channel_provider_.get(), 1275 cricket::DCT_SCTP, 1276 signaling_.get()); 1277 signaling_->SetDataChannelFactory(&fake_factory); 1278 webrtc::DataChannelInit config; 1279 config.id = 1; 1280 rtc::Buffer payload; 1281 webrtc::WriteDataChannelOpenMessage("a", config, &payload); 1282 cricket::ReceiveDataParams params; 1283 params.ssrc = config.id; 1284 EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload)); 1285 EXPECT_EQ(config.id, fake_factory.last_init().id); 1286 EXPECT_FALSE(fake_factory.last_init().negotiated); 1287 EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker, 1288 fake_factory.last_init().open_handshake_role); 1289} 1290 1291// Verifies that duplicated label from OPEN message is allowed. 1292TEST_F(MediaStreamSignalingTest, DuplicatedLabelFromOpenMessageAllowed) { 1293 AddDataChannel(cricket::DCT_SCTP, "a", -1); 1294 1295 FakeDataChannelFactory fake_factory(data_channel_provider_.get(), 1296 cricket::DCT_SCTP, 1297 signaling_.get()); 1298 signaling_->SetDataChannelFactory(&fake_factory); 1299 webrtc::DataChannelInit config; 1300 config.id = 0; 1301 rtc::Buffer payload; 1302 webrtc::WriteDataChannelOpenMessage("a", config, &payload); 1303 cricket::ReceiveDataParams params; 1304 params.ssrc = config.id; 1305 EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload)); 1306} 1307 1308// Verifies that a DataChannel closed remotely is closed locally. 1309TEST_F(MediaStreamSignalingTest, 1310 SctpDataChannelClosedLocallyWhenClosedRemotely) { 1311 webrtc::InternalDataChannelInit config; 1312 config.id = 0; 1313 1314 rtc::scoped_refptr<webrtc::DataChannel> data_channel = 1315 webrtc::DataChannel::Create( 1316 data_channel_provider_.get(), cricket::DCT_SCTP, "a", config); 1317 ASSERT_TRUE(data_channel.get() != NULL); 1318 EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, 1319 data_channel->state()); 1320 1321 EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get())); 1322 1323 signaling_->OnRemoteSctpDataChannelClosed(config.id); 1324 EXPECT_EQ(webrtc::DataChannelInterface::kClosed, data_channel->state()); 1325} 1326 1327// Verifies that DataChannel added from OPEN message is added to 1328// MediaStreamSignaling only once (webrtc issue 3778). 1329TEST_F(MediaStreamSignalingTest, DataChannelFromOpenMessageAddedOnce) { 1330 FakeDataChannelFactory fake_factory(data_channel_provider_.get(), 1331 cricket::DCT_SCTP, 1332 signaling_.get()); 1333 signaling_->SetDataChannelFactory(&fake_factory); 1334 webrtc::DataChannelInit config; 1335 config.id = 1; 1336 rtc::Buffer payload; 1337 webrtc::WriteDataChannelOpenMessage("a", config, &payload); 1338 cricket::ReceiveDataParams params; 1339 params.ssrc = config.id; 1340 EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload)); 1341 EXPECT_TRUE(signaling_->HasDataChannels()); 1342 1343 // Removes the DataChannel and verifies that no DataChannel is left. 1344 signaling_->RemoveSctpDataChannel(config.id); 1345 EXPECT_FALSE(signaling_->HasDataChannels()); 1346} 1347