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