/*
 * libjingle
 * Copyright 2012, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <string>
#include <vector>

#include "talk/app/webrtc/audiotrack.h"
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/sctputils.h"
#include "talk/app/webrtc/streamcollection.h"
#include "talk/app/webrtc/test/fakeconstraints.h"
#include "talk/app/webrtc/test/fakedatachannelprovider.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/media/base/fakemediaengine.h"
#include "talk/media/devices/fakedevicemanager.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/sessiondescription.h"
#include "talk/session/media/channelmanager.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/base/thread.h"

static const char kStreams[][8] = {"stream1", "stream2"};
static const char kAudioTracks[][32] = {"audiotrack0", "audiotrack1"};
static const char kVideoTracks[][32] = {"videotrack0", "videotrack1"};

using webrtc::AudioTrack;
using webrtc::AudioTrackInterface;
using webrtc::AudioTrackVector;
using webrtc::VideoTrack;
using webrtc::VideoTrackInterface;
using webrtc::VideoTrackVector;
using webrtc::DataChannelInterface;
using webrtc::FakeConstraints;
using webrtc::IceCandidateInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::MediaStreamTrackInterface;
using webrtc::PeerConnectionInterface;
using webrtc::SdpParseError;
using webrtc::SessionDescriptionInterface;
using webrtc::StreamCollection;
using webrtc::StreamCollectionInterface;

typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;

// Reference SDP with a MediaStream with label "stream1" and audio track with
// id "audio_1" and a video track with id "video_1;
static const char kSdpStringWithStream1[] =
    "v=0\r\n"
    "o=- 0 0 IN IP4 127.0.0.1\r\n"
    "s=-\r\n"
    "t=0 0\r\n"
    "m=audio 1 RTP/AVPF 103\r\n"
    "a=mid:audio\r\n"
    "a=rtpmap:103 ISAC/16000\r\n"
    "a=ssrc:1 cname:stream1\r\n"
    "a=ssrc:1 mslabel:stream1\r\n"
    "a=ssrc:1 label:audiotrack0\r\n"
    "m=video 1 RTP/AVPF 120\r\n"
    "a=mid:video\r\n"
    "a=rtpmap:120 VP8/90000\r\n"
    "a=ssrc:2 cname:stream1\r\n"
    "a=ssrc:2 mslabel:stream1\r\n"
    "a=ssrc:2 label:videotrack0\r\n";

// Reference SDP with two MediaStreams with label "stream1" and "stream2. Each
// MediaStreams have one audio track and one video track.
// This uses MSID.
static const char kSdpStringWith2Stream[] =
    "v=0\r\n"
    "o=- 0 0 IN IP4 127.0.0.1\r\n"
    "s=-\r\n"
    "t=0 0\r\n"
    "a=msid-semantic: WMS stream1 stream2\r\n"
    "m=audio 1 RTP/AVPF 103\r\n"
    "a=mid:audio\r\n"
    "a=rtpmap:103 ISAC/16000\r\n"
    "a=ssrc:1 cname:stream1\r\n"
    "a=ssrc:1 msid:stream1 audiotrack0\r\n"
    "a=ssrc:3 cname:stream2\r\n"
    "a=ssrc:3 msid:stream2 audiotrack1\r\n"
    "m=video 1 RTP/AVPF 120\r\n"
    "a=mid:video\r\n"
    "a=rtpmap:120 VP8/0\r\n"
    "a=ssrc:2 cname:stream1\r\n"
    "a=ssrc:2 msid:stream1 videotrack0\r\n"
    "a=ssrc:4 cname:stream2\r\n"
    "a=ssrc:4 msid:stream2 videotrack1\r\n";

// Reference SDP without MediaStreams. Msid is not supported.
static const char kSdpStringWithoutStreams[] =
    "v=0\r\n"
    "o=- 0 0 IN IP4 127.0.0.1\r\n"
    "s=-\r\n"
    "t=0 0\r\n"
    "m=audio 1 RTP/AVPF 103\r\n"
    "a=mid:audio\r\n"
    "a=rtpmap:103 ISAC/16000\r\n"
    "m=video 1 RTP/AVPF 120\r\n"
    "a=mid:video\r\n"
    "a=rtpmap:120 VP8/90000\r\n";

// Reference SDP without MediaStreams. Msid is supported.
static const char kSdpStringWithMsidWithoutStreams[] =
    "v=0\r\n"
    "o=- 0 0 IN IP4 127.0.0.1\r\n"
    "s=-\r\n"
    "t=0 0\r\n"
    "a=msid-semantic: WMS\r\n"
    "m=audio 1 RTP/AVPF 103\r\n"
    "a=mid:audio\r\n"
    "a=rtpmap:103 ISAC/16000\r\n"
    "m=video 1 RTP/AVPF 120\r\n"
    "a=mid:video\r\n"
    "a=rtpmap:120 VP8/90000\r\n";

// Reference SDP without MediaStreams and audio only.
static const char kSdpStringWithoutStreamsAudioOnly[] =
    "v=0\r\n"
    "o=- 0 0 IN IP4 127.0.0.1\r\n"
    "s=-\r\n"
    "t=0 0\r\n"
    "m=audio 1 RTP/AVPF 103\r\n"
    "a=mid:audio\r\n"
    "a=rtpmap:103 ISAC/16000\r\n";

// Reference SENDONLY SDP without MediaStreams. Msid is not supported.
static const char kSdpStringSendOnlyWithWithoutStreams[] =
    "v=0\r\n"
    "o=- 0 0 IN IP4 127.0.0.1\r\n"
    "s=-\r\n"
    "t=0 0\r\n"
    "m=audio 1 RTP/AVPF 103\r\n"
    "a=mid:audio\r\n"
    "a=sendonly"
    "a=rtpmap:103 ISAC/16000\r\n"
    "m=video 1 RTP/AVPF 120\r\n"
    "a=mid:video\r\n"
    "a=sendonly"
    "a=rtpmap:120 VP8/90000\r\n";

static const char kSdpStringInit[] =
    "v=0\r\n"
    "o=- 0 0 IN IP4 127.0.0.1\r\n"
    "s=-\r\n"
    "t=0 0\r\n"
    "a=msid-semantic: WMS\r\n";

static const char kSdpStringAudio[] =
    "m=audio 1 RTP/AVPF 103\r\n"
    "a=mid:audio\r\n"
    "a=rtpmap:103 ISAC/16000\r\n";

static const char kSdpStringVideo[] =
    "m=video 1 RTP/AVPF 120\r\n"
    "a=mid:video\r\n"
    "a=rtpmap:120 VP8/90000\r\n";

static const char kSdpStringMs1Audio0[] =
    "a=ssrc:1 cname:stream1\r\n"
    "a=ssrc:1 msid:stream1 audiotrack0\r\n";

static const char kSdpStringMs1Video0[] =
    "a=ssrc:2 cname:stream1\r\n"
    "a=ssrc:2 msid:stream1 videotrack0\r\n";

static const char kSdpStringMs1Audio1[] =
    "a=ssrc:3 cname:stream1\r\n"
    "a=ssrc:3 msid:stream1 audiotrack1\r\n";

static const char kSdpStringMs1Video1[] =
    "a=ssrc:4 cname:stream1\r\n"
    "a=ssrc:4 msid:stream1 videotrack1\r\n";

// Verifies that |options| contain all tracks in |collection| and that
// the |options| has set the the has_audio and has_video flags correct.
static void VerifyMediaOptions(StreamCollectionInterface* collection,
                               const cricket::MediaSessionOptions& options) {
  if (!collection) {
    return;
  }

  size_t stream_index = 0;
  for (size_t i = 0; i < collection->count(); ++i) {
    MediaStreamInterface* stream = collection->at(i);
    AudioTrackVector audio_tracks = stream->GetAudioTracks();
    ASSERT_GE(options.streams.size(), stream_index + audio_tracks.size());
    for (size_t j = 0; j < audio_tracks.size(); ++j) {
      webrtc::AudioTrackInterface* audio = audio_tracks[j];
      EXPECT_EQ(options.streams[stream_index].sync_label, stream->label());
      EXPECT_EQ(options.streams[stream_index++].id, audio->id());
      EXPECT_TRUE(options.has_audio);
    }
    VideoTrackVector video_tracks = stream->GetVideoTracks();
    ASSERT_GE(options.streams.size(), stream_index + video_tracks.size());
    for (size_t j = 0; j < video_tracks.size(); ++j) {
      webrtc::VideoTrackInterface* video = video_tracks[j];
      EXPECT_EQ(options.streams[stream_index].sync_label, stream->label());
      EXPECT_EQ(options.streams[stream_index++].id, video->id());
      EXPECT_TRUE(options.has_video);
    }
  }
}

static bool CompareStreamCollections(StreamCollectionInterface* s1,
                                     StreamCollectionInterface* s2) {
  if (s1 == NULL || s2 == NULL || s1->count() != s2->count())
    return false;

  for (size_t i = 0; i != s1->count(); ++i) {
    if (s1->at(i)->label() != s2->at(i)->label())
      return false;
    webrtc::AudioTrackVector audio_tracks1 = s1->at(i)->GetAudioTracks();
    webrtc::AudioTrackVector audio_tracks2 = s2->at(i)->GetAudioTracks();
    webrtc::VideoTrackVector video_tracks1 = s1->at(i)->GetVideoTracks();
    webrtc::VideoTrackVector video_tracks2 = s2->at(i)->GetVideoTracks();

    if (audio_tracks1.size() != audio_tracks2.size())
      return false;
    for (size_t j = 0; j != audio_tracks1.size(); ++j) {
       if (audio_tracks1[j]->id() != audio_tracks2[j]->id())
         return false;
    }
    if (video_tracks1.size() != video_tracks2.size())
      return false;
    for (size_t j = 0; j != video_tracks1.size(); ++j) {
      if (video_tracks1[j]->id() != video_tracks2[j]->id())
        return false;
    }
  }
  return true;
}

class FakeDataChannelFactory : public webrtc::DataChannelFactory {
 public:
  FakeDataChannelFactory(FakeDataChannelProvider* provider,
                         cricket::DataChannelType dct,
                         webrtc::MediaStreamSignaling* media_stream_signaling)
      : provider_(provider),
        type_(dct),
        media_stream_signaling_(media_stream_signaling) {}

  virtual rtc::scoped_refptr<webrtc::DataChannel> CreateDataChannel(
      const std::string& label,
      const webrtc::InternalDataChannelInit* config) {
    last_init_ = *config;
    rtc::scoped_refptr<webrtc::DataChannel> data_channel =
        webrtc::DataChannel::Create(provider_, type_, label, *config);
    media_stream_signaling_->AddDataChannel(data_channel);
    return data_channel;
  }

  const webrtc::InternalDataChannelInit& last_init() const {
      return last_init_;
  }

 private:
  FakeDataChannelProvider* provider_;
  cricket::DataChannelType type_;
  webrtc::MediaStreamSignaling* media_stream_signaling_;
  webrtc::InternalDataChannelInit last_init_;
};

class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
 public:
  MockSignalingObserver()
      : remote_media_streams_(StreamCollection::Create()) {
  }

  virtual ~MockSignalingObserver() {
  }

  // New remote stream have been discovered.
  virtual void OnAddRemoteStream(MediaStreamInterface* remote_stream) {
    remote_media_streams_->AddStream(remote_stream);
  }

  // Remote stream is no longer available.
  virtual void OnRemoveRemoteStream(MediaStreamInterface* remote_stream) {
    remote_media_streams_->RemoveStream(remote_stream);
  }

  virtual void OnAddDataChannel(DataChannelInterface* data_channel) {
  }

  virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream,
                                    AudioTrackInterface* audio_track,
                                    uint32 ssrc) {
    AddTrack(&local_audio_tracks_, stream, audio_track, ssrc);
  }

  virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream,
                                    VideoTrackInterface* video_track,
                                    uint32 ssrc) {
    AddTrack(&local_video_tracks_, stream, video_track, ssrc);
  }

  virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
                                       AudioTrackInterface* audio_track,
                                       uint32 ssrc) {
    RemoveTrack(&local_audio_tracks_, stream, audio_track);
  }

  virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
                                       VideoTrackInterface* video_track) {
    RemoveTrack(&local_video_tracks_, stream, video_track);
  }

  virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream,
                                     AudioTrackInterface* audio_track,
                                     uint32 ssrc) {
    AddTrack(&remote_audio_tracks_, stream, audio_track, ssrc);
  }

  virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream,
                                     VideoTrackInterface* video_track,
                                     uint32 ssrc) {
    AddTrack(&remote_video_tracks_, stream, video_track, ssrc);
  }

  virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream,
                                        AudioTrackInterface* audio_track) {
    RemoveTrack(&remote_audio_tracks_, stream, audio_track);
  }

  virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream,
                                        VideoTrackInterface* video_track) {
    RemoveTrack(&remote_video_tracks_, stream, video_track);
  }

  virtual void OnRemoveLocalStream(MediaStreamInterface* stream) {
  }

  MediaStreamInterface* RemoteStream(const std::string& label) {
    return remote_media_streams_->find(label);
  }

  StreamCollectionInterface* remote_streams() const {
    return remote_media_streams_;
  }

  size_t NumberOfRemoteAudioTracks() { return remote_audio_tracks_.size(); }

  void  VerifyRemoteAudioTrack(const std::string& stream_label,
                               const std::string& track_id,
                               uint32 ssrc) {
    VerifyTrack(remote_audio_tracks_, stream_label, track_id, ssrc);
  }

  size_t NumberOfRemoteVideoTracks() { return remote_video_tracks_.size(); }

  void  VerifyRemoteVideoTrack(const std::string& stream_label,
                               const std::string& track_id,
                               uint32 ssrc) {
    VerifyTrack(remote_video_tracks_, stream_label, track_id, ssrc);
  }

  size_t NumberOfLocalAudioTracks() { return local_audio_tracks_.size(); }
  void  VerifyLocalAudioTrack(const std::string& stream_label,
                              const std::string& track_id,
                              uint32 ssrc) {
    VerifyTrack(local_audio_tracks_, stream_label, track_id, ssrc);
  }

  size_t NumberOfLocalVideoTracks() { return local_video_tracks_.size(); }

  void  VerifyLocalVideoTrack(const std::string& stream_label,
                              const std::string& track_id,
                              uint32 ssrc) {
    VerifyTrack(local_video_tracks_, stream_label, track_id, ssrc);
  }

 private:
  struct TrackInfo {
    TrackInfo() {}
    TrackInfo(const std::string& stream_label, const std::string track_id,
              uint32 ssrc)
        : stream_label(stream_label),
          track_id(track_id),
          ssrc(ssrc) {
    }
    std::string stream_label;
    std::string track_id;
    uint32 ssrc;
  };
  typedef std::vector<TrackInfo> TrackInfos;

  void AddTrack(TrackInfos* track_infos, MediaStreamInterface* stream,
                MediaStreamTrackInterface* track,
                uint32 ssrc) {
    (*track_infos).push_back(TrackInfo(stream->label(), track->id(),
                                       ssrc));
  }

  void RemoveTrack(TrackInfos* track_infos, MediaStreamInterface* stream,
                   MediaStreamTrackInterface* track) {
    for (TrackInfos::iterator it = track_infos->begin();
         it != track_infos->end(); ++it) {
      if (it->stream_label == stream->label() && it->track_id == track->id()) {
        track_infos->erase(it);
        return;
      }
    }
    ADD_FAILURE();
  }

  const TrackInfo* FindTrackInfo(const TrackInfos& infos,
                                 const std::string& stream_label,
                                 const std::string track_id) const {
    for (TrackInfos::const_iterator it = infos.begin();
        it != infos.end(); ++it) {
      if (it->stream_label == stream_label && it->track_id == track_id)
        return &*it;
    }
    return NULL;
  }


  void VerifyTrack(const TrackInfos& track_infos,
                   const std::string& stream_label,
                   const std::string& track_id,
                   uint32 ssrc) {
    const TrackInfo* track_info = FindTrackInfo(track_infos,
                                                stream_label,
                                                track_id);
    ASSERT_TRUE(track_info != NULL);
    EXPECT_EQ(ssrc, track_info->ssrc);
  }

  TrackInfos remote_audio_tracks_;
  TrackInfos remote_video_tracks_;
  TrackInfos local_audio_tracks_;
  TrackInfos local_video_tracks_;

  rtc::scoped_refptr<StreamCollection> remote_media_streams_;
};

class MediaStreamSignalingForTest : public webrtc::MediaStreamSignaling {
 public:
  MediaStreamSignalingForTest(MockSignalingObserver* observer,
                              cricket::ChannelManager* channel_manager)
      : webrtc::MediaStreamSignaling(rtc::Thread::Current(), observer,
                                     channel_manager) {
  };

  using webrtc::MediaStreamSignaling::GetOptionsForOffer;
  using webrtc::MediaStreamSignaling::GetOptionsForAnswer;
  using webrtc::MediaStreamSignaling::OnRemoteDescriptionChanged;
  using webrtc::MediaStreamSignaling::remote_streams;
};

class MediaStreamSignalingTest: public testing::Test {
 protected:
  virtual void SetUp() {
    observer_.reset(new MockSignalingObserver());
    channel_manager_.reset(
        new cricket::ChannelManager(new cricket::FakeMediaEngine(),
                                    new cricket::FakeDeviceManager(),
                                    rtc::Thread::Current()));
    signaling_.reset(new MediaStreamSignalingForTest(observer_.get(),
                                                     channel_manager_.get()));
    data_channel_provider_.reset(new FakeDataChannelProvider());
  }

  // Create a collection of streams.
  // CreateStreamCollection(1) creates a collection that
  // correspond to kSdpString1.
  // CreateStreamCollection(2) correspond to kSdpString2.
  rtc::scoped_refptr<StreamCollection>
  CreateStreamCollection(int number_of_streams) {
    rtc::scoped_refptr<StreamCollection> local_collection(
        StreamCollection::Create());

    for (int i = 0; i < number_of_streams; ++i) {
      rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
          webrtc::MediaStream::Create(kStreams[i]));

      // Add a local audio track.
      rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
          webrtc::AudioTrack::Create(kAudioTracks[i], NULL));
      stream->AddTrack(audio_track);

      // Add a local video track.
      rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
          webrtc::VideoTrack::Create(kVideoTracks[i], NULL));
      stream->AddTrack(video_track);

      local_collection->AddStream(stream);
    }
    return local_collection;
  }

  // This functions Creates a MediaStream with label kStreams[0] and
  // |number_of_audio_tracks| and |number_of_video_tracks| tracks and the
  // corresponding SessionDescriptionInterface. The SessionDescriptionInterface
  // is returned in |desc| and the MediaStream is stored in
  // |reference_collection_|
  void CreateSessionDescriptionAndReference(
      size_t number_of_audio_tracks,
      size_t number_of_video_tracks,
      SessionDescriptionInterface** desc) {
    ASSERT_TRUE(desc != NULL);
    ASSERT_LE(number_of_audio_tracks, 2u);
    ASSERT_LE(number_of_video_tracks, 2u);

    reference_collection_ = StreamCollection::Create();
    std::string sdp_ms1 = std::string(kSdpStringInit);

    std::string mediastream_label = kStreams[0];

    rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
            webrtc::MediaStream::Create(mediastream_label));
    reference_collection_->AddStream(stream);

    if (number_of_audio_tracks > 0) {
      sdp_ms1 += std::string(kSdpStringAudio);
      sdp_ms1 += std::string(kSdpStringMs1Audio0);
      AddAudioTrack(kAudioTracks[0], stream);
    }
    if (number_of_audio_tracks > 1) {
      sdp_ms1 += kSdpStringMs1Audio1;
      AddAudioTrack(kAudioTracks[1], stream);
    }

    if (number_of_video_tracks > 0) {
      sdp_ms1 += std::string(kSdpStringVideo);
      sdp_ms1 += std::string(kSdpStringMs1Video0);
      AddVideoTrack(kVideoTracks[0], stream);
    }
    if (number_of_video_tracks > 1) {
      sdp_ms1 += kSdpStringMs1Video1;
      AddVideoTrack(kVideoTracks[1], stream);
    }

    *desc = webrtc::CreateSessionDescription(
        SessionDescriptionInterface::kOffer, sdp_ms1, NULL);
  }

  void AddAudioTrack(const std::string& track_id,
                     MediaStreamInterface* stream) {
    rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
        webrtc::AudioTrack::Create(track_id, NULL));
    ASSERT_TRUE(stream->AddTrack(audio_track));
  }

  void AddVideoTrack(const std::string& track_id,
                     MediaStreamInterface* stream) {
    rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
        webrtc::VideoTrack::Create(track_id, NULL));
    ASSERT_TRUE(stream->AddTrack(video_track));
  }

  rtc::scoped_refptr<webrtc::DataChannel> AddDataChannel(
      cricket::DataChannelType type, const std::string& label, int id) {
    webrtc::InternalDataChannelInit config;
    config.id = id;
    rtc::scoped_refptr<webrtc::DataChannel> data_channel(
        webrtc::DataChannel::Create(
            data_channel_provider_.get(), type, label, config));
    EXPECT_TRUE(data_channel.get() != NULL);
    EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get()));
    return data_channel;
  }

  // ChannelManager is used by VideoSource, so it should be released after all
  // the video tracks. Put it as the first private variable should ensure that.
  rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
  rtc::scoped_refptr<StreamCollection> reference_collection_;
  rtc::scoped_ptr<MockSignalingObserver> observer_;
  rtc::scoped_ptr<MediaStreamSignalingForTest> signaling_;
  rtc::scoped_ptr<FakeDataChannelProvider> data_channel_provider_;
};

TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidAudioOption) {
  RTCOfferAnswerOptions rtc_options;
  rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;

  cricket::MediaSessionOptions options;
  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));

  rtc_options.offer_to_receive_audio =
      RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
}


TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidVideoOption) {
  RTCOfferAnswerOptions rtc_options;
  rtc_options.offer_to_receive_video =
      RTCOfferAnswerOptions::kUndefined - 1;

  cricket::MediaSessionOptions options;
  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));

  rtc_options.offer_to_receive_video =
      RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
}

// Test that a MediaSessionOptions is created for an offer if
// OfferToReceiveAudio and OfferToReceiveVideo options are set but no
// MediaStreams are sent.
TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
  RTCOfferAnswerOptions rtc_options;
  rtc_options.offer_to_receive_audio = 1;
  rtc_options.offer_to_receive_video = 1;

  cricket::MediaSessionOptions options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  EXPECT_TRUE(options.has_audio);
  EXPECT_TRUE(options.has_video);
  EXPECT_TRUE(options.bundle_enabled);
}

// Test that a correct MediaSessionOptions is created for an offer if
// OfferToReceiveAudio is set but no MediaStreams are sent.
TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudio) {
  RTCOfferAnswerOptions rtc_options;
  rtc_options.offer_to_receive_audio = 1;

  cricket::MediaSessionOptions options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  EXPECT_TRUE(options.has_audio);
  EXPECT_FALSE(options.has_video);
  EXPECT_TRUE(options.bundle_enabled);
}

// Test that a correct MediaSessionOptions is created for an offer if
// the default OfferOptons is used or MediaStreams are sent.
TEST_F(MediaStreamSignalingTest, GetDefaultMediaSessionOptionsForOffer) {
  RTCOfferAnswerOptions rtc_options;

  cricket::MediaSessionOptions options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  EXPECT_FALSE(options.has_audio);
  EXPECT_FALSE(options.has_video);
  EXPECT_FALSE(options.bundle_enabled);
  EXPECT_TRUE(options.vad_enabled);
  EXPECT_FALSE(options.transport_options.ice_restart);
}

// Test that a correct MediaSessionOptions is created for an offer if
// OfferToReceiveVideo is set but no MediaStreams are sent.
TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithVideo) {
  RTCOfferAnswerOptions rtc_options;
  rtc_options.offer_to_receive_audio = 0;
  rtc_options.offer_to_receive_video = 1;

  cricket::MediaSessionOptions options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  EXPECT_FALSE(options.has_audio);
  EXPECT_TRUE(options.has_video);
  EXPECT_TRUE(options.bundle_enabled);
}

// Test that a correct MediaSessionOptions is created for an offer if
// UseRtpMux is set to false.
TEST_F(MediaStreamSignalingTest,
       GetMediaSessionOptionsForOfferWithBundleDisabled) {
  RTCOfferAnswerOptions rtc_options;
  rtc_options.offer_to_receive_audio = 1;
  rtc_options.offer_to_receive_video = 1;
  rtc_options.use_rtp_mux = false;

  cricket::MediaSessionOptions options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  EXPECT_TRUE(options.has_audio);
  EXPECT_TRUE(options.has_video);
  EXPECT_FALSE(options.bundle_enabled);
}

// Test that a correct MediaSessionOptions is created to restart ice if
// IceRestart is set. It also tests that subsequent MediaSessionOptions don't
// have |transport_options.ice_restart| set.
TEST_F(MediaStreamSignalingTest,
       GetMediaSessionOptionsForOfferWithIceRestart) {
  RTCOfferAnswerOptions rtc_options;
  rtc_options.ice_restart = true;

  cricket::MediaSessionOptions options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  EXPECT_TRUE(options.transport_options.ice_restart);

  rtc_options = RTCOfferAnswerOptions();
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  EXPECT_FALSE(options.transport_options.ice_restart);
}

// Test that a correct MediaSessionOptions are created for an offer if
// a MediaStream is sent and later updated with a new track.
// MediaConstraints are not used.
TEST_F(MediaStreamSignalingTest, AddTrackToLocalMediaStream) {
  RTCOfferAnswerOptions rtc_options;
  rtc::scoped_refptr<StreamCollection> local_streams(
      CreateStreamCollection(1));
  MediaStreamInterface* local_stream = local_streams->at(0);
  EXPECT_TRUE(signaling_->AddLocalStream(local_stream));
  cricket::MediaSessionOptions options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  VerifyMediaOptions(local_streams, options);

  cricket::MediaSessionOptions updated_options;
  local_stream->AddTrack(AudioTrack::Create(kAudioTracks[1], NULL));
  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
  VerifyMediaOptions(local_streams, options);
}

// Test that the MediaConstraints in an answer don't affect if audio and video
// is offered in an offer but that if kOfferToReceiveAudio or
// kOfferToReceiveVideo constraints are true in an offer, the media type will be
// included in subsequent answers.
TEST_F(MediaStreamSignalingTest, MediaConstraintsInAnswer) {
  FakeConstraints answer_c;
  answer_c.SetMandatoryReceiveAudio(true);
  answer_c.SetMandatoryReceiveVideo(true);

  cricket::MediaSessionOptions answer_options;
  EXPECT_TRUE(signaling_->GetOptionsForAnswer(&answer_c, &answer_options));
  EXPECT_TRUE(answer_options.has_audio);
  EXPECT_TRUE(answer_options.has_video);

  RTCOfferAnswerOptions rtc_offer_optoins;

  cricket::MediaSessionOptions offer_options;
  EXPECT_TRUE(
      signaling_->GetOptionsForOffer(rtc_offer_optoins, &offer_options));
  EXPECT_FALSE(offer_options.has_audio);
  EXPECT_FALSE(offer_options.has_video);

  RTCOfferAnswerOptions updated_rtc_offer_optoins;
  updated_rtc_offer_optoins.offer_to_receive_audio = 1;
  updated_rtc_offer_optoins.offer_to_receive_video = 1;

  cricket::MediaSessionOptions updated_offer_options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(updated_rtc_offer_optoins,
                                             &updated_offer_options));
  EXPECT_TRUE(updated_offer_options.has_audio);
  EXPECT_TRUE(updated_offer_options.has_video);

  // Since an offer has been created with both audio and video, subsequent
  // offers and answers should contain both audio and video.
  // Answers will only contain the media types that exist in the offer
  // regardless of the value of |updated_answer_options.has_audio| and
  // |updated_answer_options.has_video|.
  FakeConstraints updated_answer_c;
  answer_c.SetMandatoryReceiveAudio(false);
  answer_c.SetMandatoryReceiveVideo(false);

  cricket::MediaSessionOptions updated_answer_options;
  EXPECT_TRUE(signaling_->GetOptionsForAnswer(&updated_answer_c,
                                              &updated_answer_options));
  EXPECT_TRUE(updated_answer_options.has_audio);
  EXPECT_TRUE(updated_answer_options.has_video);

  RTCOfferAnswerOptions default_rtc_options;
  EXPECT_TRUE(signaling_->GetOptionsForOffer(default_rtc_options,
                                             &updated_offer_options));
  // By default, |has_audio| or |has_video| are false if there is no media
  // track.
  EXPECT_FALSE(updated_offer_options.has_audio);
  EXPECT_FALSE(updated_offer_options.has_video);
}

// This test verifies that the remote MediaStreams corresponding to a received
// SDP string is created. In this test the two separate MediaStreams are
// signaled.
TEST_F(MediaStreamSignalingTest, UpdateRemoteStreams) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithStream1, NULL));
  EXPECT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());

  rtc::scoped_refptr<StreamCollection> reference(
      CreateStreamCollection(1));
  EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
                                       reference.get()));
  EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
                                       reference.get()));
  EXPECT_EQ(1u, observer_->NumberOfRemoteAudioTracks());
  observer_->VerifyRemoteAudioTrack(kStreams[0], kAudioTracks[0], 1);
  EXPECT_EQ(1u, observer_->NumberOfRemoteVideoTracks());
  observer_->VerifyRemoteVideoTrack(kStreams[0], kVideoTracks[0], 2);
  ASSERT_EQ(1u, observer_->remote_streams()->count());
  MediaStreamInterface* remote_stream =  observer_->remote_streams()->at(0);
  EXPECT_TRUE(remote_stream->GetVideoTracks()[0]->GetSource() != NULL);

  // Create a session description based on another SDP with another
  // MediaStream.
  rtc::scoped_ptr<SessionDescriptionInterface> update_desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWith2Stream, NULL));
  EXPECT_TRUE(update_desc != NULL);
  signaling_->OnRemoteDescriptionChanged(update_desc.get());

  rtc::scoped_refptr<StreamCollection> reference2(
      CreateStreamCollection(2));
  EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
                                       reference2.get()));
  EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
                                       reference2.get()));

  EXPECT_EQ(2u, observer_->NumberOfRemoteAudioTracks());
  observer_->VerifyRemoteAudioTrack(kStreams[0], kAudioTracks[0], 1);
  observer_->VerifyRemoteAudioTrack(kStreams[1], kAudioTracks[1], 3);
  EXPECT_EQ(2u, observer_->NumberOfRemoteVideoTracks());
  observer_->VerifyRemoteVideoTrack(kStreams[0], kVideoTracks[0], 2);
  observer_->VerifyRemoteVideoTrack(kStreams[1], kVideoTracks[1], 4);
}

// This test verifies that the remote MediaStreams corresponding to a received
// SDP string is created. In this test the same remote MediaStream is signaled
// but MediaStream tracks are added and removed.
TEST_F(MediaStreamSignalingTest, AddRemoveTrackFromExistingRemoteMediaStream) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1;
  CreateSessionDescriptionAndReference(1, 1, desc_ms1.use());
  signaling_->OnRemoteDescriptionChanged(desc_ms1.get());
  EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
                                       reference_collection_));

  // Add extra audio and video tracks to the same MediaStream.
  rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1_two_tracks;
  CreateSessionDescriptionAndReference(2, 2, desc_ms1_two_tracks.use());
  signaling_->OnRemoteDescriptionChanged(desc_ms1_two_tracks.get());
  EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
                                       reference_collection_));
  EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
                                       reference_collection_));

  // Remove the extra audio and video tracks again.
  rtc::scoped_ptr<SessionDescriptionInterface> desc_ms2;
  CreateSessionDescriptionAndReference(1, 1, desc_ms2.use());
  signaling_->OnRemoteDescriptionChanged(desc_ms2.get());
  EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
                                       reference_collection_));
  EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
                                       reference_collection_));
}

// This test that remote tracks are ended if a
// local session description is set that rejects the media content type.
TEST_F(MediaStreamSignalingTest, RejectMediaContent) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithStream1, NULL));
  EXPECT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());

  ASSERT_EQ(1u, observer_->remote_streams()->count());
  MediaStreamInterface* remote_stream =  observer_->remote_streams()->at(0);
  ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
  ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());

  rtc::scoped_refptr<webrtc::VideoTrackInterface> remote_video =
      remote_stream->GetVideoTracks()[0];
  EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_video->state());
  rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_audio =
      remote_stream->GetAudioTracks()[0];
  EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());

  cricket::ContentInfo* video_info =
      desc->description()->GetContentByName("video");
  ASSERT_TRUE(video_info != NULL);
  video_info->rejected = true;
  signaling_->OnLocalDescriptionChanged(desc.get());
  EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
  EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());

  cricket::ContentInfo* audio_info =
      desc->description()->GetContentByName("audio");
  ASSERT_TRUE(audio_info != NULL);
  audio_info->rejected = true;
  signaling_->OnLocalDescriptionChanged(desc.get());
  EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_audio->state());
}

// This test that it won't crash if the remote track as been removed outside
// of MediaStreamSignaling and then MediaStreamSignaling tries to reject
// this track.
TEST_F(MediaStreamSignalingTest, RemoveTrackThenRejectMediaContent) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithStream1, NULL));
  EXPECT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());

  MediaStreamInterface* remote_stream =  observer_->remote_streams()->at(0);
  remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
  remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);

  cricket::ContentInfo* video_info =
      desc->description()->GetContentByName("video");
  video_info->rejected = true;
  signaling_->OnLocalDescriptionChanged(desc.get());

  cricket::ContentInfo* audio_info =
      desc->description()->GetContentByName("audio");
  audio_info->rejected = true;
  signaling_->OnLocalDescriptionChanged(desc.get());

  // No crash is a pass.
}

// This tests that a default MediaStream is created if a remote session
// description doesn't contain any streams and no MSID support.
// It also tests that the default stream is updated if a video m-line is added
// in a subsequent session description.
TEST_F(MediaStreamSignalingTest, SdpWithoutMsidCreatesDefaultStream) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc_audio_only(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithoutStreamsAudioOnly,
                                       NULL));
  ASSERT_TRUE(desc_audio_only != NULL);
  signaling_->OnRemoteDescriptionChanged(desc_audio_only.get());

  EXPECT_EQ(1u, signaling_->remote_streams()->count());
  ASSERT_EQ(1u, observer_->remote_streams()->count());
  MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);

  EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
  EXPECT_EQ(0u, remote_stream->GetVideoTracks().size());
  EXPECT_EQ("default", remote_stream->label());

  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithoutStreams, NULL));
  ASSERT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());
  EXPECT_EQ(1u, signaling_->remote_streams()->count());
  ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
  EXPECT_EQ("defaulta0", remote_stream->GetAudioTracks()[0]->id());
  ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
  EXPECT_EQ("defaultv0", remote_stream->GetVideoTracks()[0]->id());
  observer_->VerifyRemoteAudioTrack("default", "defaulta0", 0);
  observer_->VerifyRemoteVideoTrack("default", "defaultv0", 0);
}

// This tests that a default MediaStream is created if a remote session
// description doesn't contain any streams and media direction is send only.
TEST_F(MediaStreamSignalingTest, RecvOnlySdpWithoutMsidCreatesDefaultStream) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringSendOnlyWithWithoutStreams,
                                       NULL));
  ASSERT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());

  EXPECT_EQ(1u, signaling_->remote_streams()->count());
  ASSERT_EQ(1u, observer_->remote_streams()->count());
  MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);

  EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
  EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
  EXPECT_EQ("default", remote_stream->label());
}

// This tests that it won't crash when MediaStreamSignaling tries to remove
//  a remote track that as already been removed from the mediastream.
TEST_F(MediaStreamSignalingTest, RemoveAlreadyGoneRemoteStream) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc_audio_only(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithoutStreams,
                                       NULL));
  ASSERT_TRUE(desc_audio_only != NULL);
  signaling_->OnRemoteDescriptionChanged(desc_audio_only.get());
  MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
  remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
  remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);

  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithoutStreams, NULL));
  ASSERT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());

  // No crash is a pass.
}

// This tests that a default MediaStream is created if the remote session
// description doesn't contain any streams and don't contain an indication if
// MSID is supported.
TEST_F(MediaStreamSignalingTest,
       SdpWithoutMsidAndStreamsCreatesDefaultStream) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithoutStreams,
                                       NULL));
  ASSERT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());

  ASSERT_EQ(1u, observer_->remote_streams()->count());
  MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
  EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
  EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
}

// This tests that a default MediaStream is not created if the remote session
// description doesn't contain any streams but does support MSID.
TEST_F(MediaStreamSignalingTest, SdpWitMsidDontCreatesDefaultStream) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc_msid_without_streams(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithMsidWithoutStreams,
                                       NULL));
  signaling_->OnRemoteDescriptionChanged(desc_msid_without_streams.get());
  EXPECT_EQ(0u, observer_->remote_streams()->count());
}

// This test that a default MediaStream is not created if a remote session
// description is updated to not have any MediaStreams.
TEST_F(MediaStreamSignalingTest, VerifyDefaultStreamIsNotCreated) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithStream1,
                                       NULL));
  ASSERT_TRUE(desc != NULL);
  signaling_->OnRemoteDescriptionChanged(desc.get());
  rtc::scoped_refptr<StreamCollection> reference(
      CreateStreamCollection(1));
  EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
                                       reference.get()));

  rtc::scoped_ptr<SessionDescriptionInterface> desc_without_streams(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       kSdpStringWithoutStreams,
                                       NULL));
  signaling_->OnRemoteDescriptionChanged(desc_without_streams.get());
  EXPECT_EQ(0u, observer_->remote_streams()->count());
}

// This test that the correct MediaStreamSignalingObserver methods are called
// when MediaStreamSignaling::OnLocalDescriptionChanged is called with an
// updated local session description.
TEST_F(MediaStreamSignalingTest, LocalDescriptionChanged) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
  CreateSessionDescriptionAndReference(2, 2, desc_1.use());

  signaling_->AddLocalStream(reference_collection_->at(0));
  signaling_->OnLocalDescriptionChanged(desc_1.get());
  EXPECT_EQ(2u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(2u, observer_->NumberOfLocalVideoTracks());
  observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
  observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);
  observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[1], 3);
  observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[1], 4);

  // Remove an audio and video track.
  rtc::scoped_ptr<SessionDescriptionInterface> desc_2;
  CreateSessionDescriptionAndReference(1, 1, desc_2.use());
  signaling_->OnLocalDescriptionChanged(desc_2.get());
  EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
  observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
  observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);
}

// This test that the correct MediaStreamSignalingObserver methods are called
// when MediaStreamSignaling::AddLocalStream is called after
// MediaStreamSignaling::OnLocalDescriptionChanged is called.
TEST_F(MediaStreamSignalingTest, AddLocalStreamAfterLocalDescriptionChanged) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
  CreateSessionDescriptionAndReference(2, 2, desc_1.use());

  signaling_->OnLocalDescriptionChanged(desc_1.get());
  EXPECT_EQ(0u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(0u, observer_->NumberOfLocalVideoTracks());

  signaling_->AddLocalStream(reference_collection_->at(0));
  EXPECT_EQ(2u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(2u, observer_->NumberOfLocalVideoTracks());
  observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
  observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);
  observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[1], 3);
  observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[1], 4);
}

// This test that the correct MediaStreamSignalingObserver methods are called
// if the ssrc on a local track is changed when
// MediaStreamSignaling::OnLocalDescriptionChanged is called.
TEST_F(MediaStreamSignalingTest, ChangeSsrcOnTrackInLocalSessionDescription) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc;
  CreateSessionDescriptionAndReference(1, 1, desc.use());

  signaling_->AddLocalStream(reference_collection_->at(0));
  signaling_->OnLocalDescriptionChanged(desc.get());
  EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
  observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
  observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);

  // Change the ssrc of the audio and video track.
  std::string sdp;
  desc->ToString(&sdp);
  std::string ssrc_org = "a=ssrc:1";
  std::string ssrc_to = "a=ssrc:97";
  rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(),
                             ssrc_to.c_str(), ssrc_to.length(),
                             &sdp);
  ssrc_org = "a=ssrc:2";
  ssrc_to = "a=ssrc:98";
  rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(),
                             ssrc_to.c_str(), ssrc_to.length(),
                             &sdp);
  rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       sdp, NULL));

  signaling_->OnLocalDescriptionChanged(updated_desc.get());
  EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
  observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 97);
  observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 98);
}

// This test that the correct MediaStreamSignalingObserver methods are called
// if a new session description is set with the same tracks but they are now
// sent on a another MediaStream.
TEST_F(MediaStreamSignalingTest, SignalSameTracksInSeparateMediaStream) {
  rtc::scoped_ptr<SessionDescriptionInterface> desc;
  CreateSessionDescriptionAndReference(1, 1, desc.use());

  signaling_->AddLocalStream(reference_collection_->at(0));
  signaling_->OnLocalDescriptionChanged(desc.get());
  EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());

  std::string stream_label_0 = kStreams[0];
  observer_->VerifyLocalAudioTrack(stream_label_0, kAudioTracks[0], 1);
  observer_->VerifyLocalVideoTrack(stream_label_0, kVideoTracks[0], 2);

  // Add a new MediaStream but with the same tracks as in the first stream.
  std::string stream_label_1 = kStreams[1];
  rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_1(
      webrtc::MediaStream::Create(kStreams[1]));
  stream_1->AddTrack(reference_collection_->at(0)->GetVideoTracks()[0]);
  stream_1->AddTrack(reference_collection_->at(0)->GetAudioTracks()[0]);
  signaling_->AddLocalStream(stream_1);

  // Replace msid in the original SDP.
  std::string sdp;
  desc->ToString(&sdp);
  rtc::replace_substrs(
      kStreams[0], strlen(kStreams[0]), kStreams[1], strlen(kStreams[1]), &sdp);

  rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
      webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
                                       sdp, NULL));

  signaling_->OnLocalDescriptionChanged(updated_desc.get());
  observer_->VerifyLocalAudioTrack(kStreams[1], kAudioTracks[0], 1);
  observer_->VerifyLocalVideoTrack(kStreams[1], kVideoTracks[0], 2);
  EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
  EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
}

// Verifies that an even SCTP id is allocated for SSL_CLIENT and an odd id for
// SSL_SERVER.
TEST_F(MediaStreamSignalingTest, SctpIdAllocationBasedOnRole) {
  int id;
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &id));
  EXPECT_EQ(1, id);
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &id));
  EXPECT_EQ(0, id);
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &id));
  EXPECT_EQ(3, id);
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &id));
  EXPECT_EQ(2, id);
}

// Verifies that SCTP ids of existing DataChannels are not reused.
TEST_F(MediaStreamSignalingTest, SctpIdAllocationNoReuse) {
  int old_id = 1;
  AddDataChannel(cricket::DCT_SCTP, "a", old_id);

  int new_id;
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &new_id));
  EXPECT_NE(old_id, new_id);

  // Creates a DataChannel with id 0.
  old_id = 0;
  AddDataChannel(cricket::DCT_SCTP, "a", old_id);
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &new_id));
  EXPECT_NE(old_id, new_id);
}

// Verifies that SCTP ids of removed DataChannels can be reused.
TEST_F(MediaStreamSignalingTest, SctpIdReusedForRemovedDataChannel) {
  int odd_id = 1;
  int even_id = 0;
  AddDataChannel(cricket::DCT_SCTP, "a", odd_id);
  AddDataChannel(cricket::DCT_SCTP, "a", even_id);

  int allocated_id = -1;
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER,
                                          &allocated_id));
  EXPECT_EQ(odd_id + 2, allocated_id);
  AddDataChannel(cricket::DCT_SCTP, "a", allocated_id);

  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT,
                                          &allocated_id));
  EXPECT_EQ(even_id + 2, allocated_id);
  AddDataChannel(cricket::DCT_SCTP, "a", allocated_id);

  signaling_->RemoveSctpDataChannel(odd_id);
  signaling_->RemoveSctpDataChannel(even_id);

  // Verifies that removed DataChannel ids are reused.
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER,
                                          &allocated_id));
  EXPECT_EQ(odd_id, allocated_id);

  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT,
                                          &allocated_id));
  EXPECT_EQ(even_id, allocated_id);

  // Verifies that used higher DataChannel ids are not reused.
  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER,
                                          &allocated_id));
  EXPECT_NE(odd_id + 2, allocated_id);

  ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT,
                                          &allocated_id));
  EXPECT_NE(even_id + 2, allocated_id);

}

// Verifies that duplicated label is not allowed for RTP data channel.
TEST_F(MediaStreamSignalingTest, RtpDuplicatedLabelNotAllowed) {
  AddDataChannel(cricket::DCT_RTP, "a", -1);

  webrtc::InternalDataChannelInit config;
  rtc::scoped_refptr<webrtc::DataChannel> data_channel =
      webrtc::DataChannel::Create(
          data_channel_provider_.get(), cricket::DCT_RTP, "a", config);
  ASSERT_TRUE(data_channel.get() != NULL);
  EXPECT_FALSE(signaling_->AddDataChannel(data_channel.get()));
}

// Verifies that duplicated label is allowed for SCTP data channel.
TEST_F(MediaStreamSignalingTest, SctpDuplicatedLabelAllowed) {
  AddDataChannel(cricket::DCT_SCTP, "a", -1);
  AddDataChannel(cricket::DCT_SCTP, "a", -1);
}

// Verifies the correct configuration is used to create DataChannel from an OPEN
// message.
TEST_F(MediaStreamSignalingTest, CreateDataChannelFromOpenMessage) {
  FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
                                      cricket::DCT_SCTP,
                                      signaling_.get());
  signaling_->SetDataChannelFactory(&fake_factory);
  webrtc::DataChannelInit config;
  config.id = 1;
  rtc::Buffer payload;
  webrtc::WriteDataChannelOpenMessage("a", config, &payload);
  cricket::ReceiveDataParams params;
  params.ssrc = config.id;
  EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
  EXPECT_EQ(config.id, fake_factory.last_init().id);
  EXPECT_FALSE(fake_factory.last_init().negotiated);
  EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker,
            fake_factory.last_init().open_handshake_role);
}

// Verifies that duplicated label from OPEN message is allowed.
TEST_F(MediaStreamSignalingTest, DuplicatedLabelFromOpenMessageAllowed) {
  AddDataChannel(cricket::DCT_SCTP, "a", -1);

  FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
                                      cricket::DCT_SCTP,
                                      signaling_.get());
  signaling_->SetDataChannelFactory(&fake_factory);
  webrtc::DataChannelInit config;
  config.id = 0;
  rtc::Buffer payload;
  webrtc::WriteDataChannelOpenMessage("a", config, &payload);
  cricket::ReceiveDataParams params;
  params.ssrc = config.id;
  EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
}

// Verifies that a DataChannel closed remotely is closed locally.
TEST_F(MediaStreamSignalingTest,
       SctpDataChannelClosedLocallyWhenClosedRemotely) {
  webrtc::InternalDataChannelInit config;
  config.id = 0;

  rtc::scoped_refptr<webrtc::DataChannel> data_channel =
      webrtc::DataChannel::Create(
          data_channel_provider_.get(), cricket::DCT_SCTP, "a", config);
  ASSERT_TRUE(data_channel.get() != NULL);
  EXPECT_EQ(webrtc::DataChannelInterface::kConnecting,
            data_channel->state());

  EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get()));

  signaling_->OnRemoteSctpDataChannelClosed(config.id);
  EXPECT_EQ(webrtc::DataChannelInterface::kClosed, data_channel->state());
}

// Verifies that DataChannel added from OPEN message is added to
// MediaStreamSignaling only once (webrtc issue 3778).
TEST_F(MediaStreamSignalingTest, DataChannelFromOpenMessageAddedOnce) {
  FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
                                      cricket::DCT_SCTP,
                                      signaling_.get());
  signaling_->SetDataChannelFactory(&fake_factory);
  webrtc::DataChannelInit config;
  config.id = 1;
  rtc::Buffer payload;
  webrtc::WriteDataChannelOpenMessage("a", config, &payload);
  cricket::ReceiveDataParams params;
  params.ssrc = config.id;
  EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
  EXPECT_TRUE(signaling_->HasDataChannels());

  // Removes the DataChannel and verifies that no DataChannel is left.
  signaling_->RemoveSctpDataChannel(config.id);
  EXPECT_FALSE(signaling_->HasDataChannels());
}
