/*
 *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <memory>

#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/create_peerconnection_factory.h"
#include "api/peer_connection_proxy.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "p2p/base/fake_port_allocator.h"
#include "p2p/base/test_stun_server.h"
#include "p2p/client/basic_port_allocator.h"
#include "pc/media_session.h"
#include "pc/peer_connection.h"
#include "pc/peer_connection_wrapper.h"
#include "pc/sdp_utils.h"
#ifdef WEBRTC_ANDROID
#include "pc/test/android_test_initializer.h"
#endif
#include "pc/test/fake_audio_capture_module.h"
#include "rtc_base/fake_network.h"
#include "rtc_base/gunit.h"
#include "rtc_base/virtual_socket_server.h"
#include "test/gmock.h"

namespace webrtc {

using BundlePolicy = PeerConnectionInterface::BundlePolicy;
using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
using RtcpMuxPolicy = PeerConnectionInterface::RtcpMuxPolicy;
using rtc::SocketAddress;
using ::testing::Combine;
using ::testing::ElementsAre;
using ::testing::UnorderedElementsAre;
using ::testing::Values;

constexpr int kDefaultTimeout = 10000;

// TODO(steveanton): These tests should be rewritten to use the standard
// RtpSenderInterface/DtlsTransportInterface objects once they're available in
// the API. The RtpSender can be used to determine which transport a given media
// will use: https://www.w3.org/TR/webrtc/#dom-rtcrtpsender-transport
// Should also be able to remove GetTransceiversForTesting at that point.

class FakeNetworkManagerWithNoAnyNetwork : public rtc::FakeNetworkManager {
 public:
  void GetAnyAddressNetworks(NetworkList* networks) override {
    // This function allocates networks that are owned by the
    // NetworkManager. But some tests assume that they can release
    // all networks independent of the network manager.
    // In order to prevent use-after-free issues, don't allow this
    // function to have any effect when run in tests.
    RTC_LOG(LS_INFO) << "FakeNetworkManager::GetAnyAddressNetworks ignored";
  }
};

class PeerConnectionWrapperForBundleTest : public PeerConnectionWrapper {
 public:
  using PeerConnectionWrapper::PeerConnectionWrapper;

  bool AddIceCandidateToMedia(cricket::Candidate* candidate,
                              cricket::MediaType media_type) {
    auto* desc = pc()->remote_description()->description();
    for (size_t i = 0; i < desc->contents().size(); i++) {
      const auto& content = desc->contents()[i];
      if (content.media_description()->type() == media_type) {
        candidate->set_transport_name(content.name);
        std::unique_ptr<IceCandidateInterface> jsep_candidate =
            CreateIceCandidate(content.name, i, *candidate);
        return pc()->AddIceCandidate(jsep_candidate.get());
      }
    }
    RTC_NOTREACHED();
    return false;
  }

  RtpTransportInternal* voice_rtp_transport() {
    return (voice_channel() ? voice_channel()->rtp_transport() : nullptr);
  }

  cricket::VoiceChannel* voice_channel() {
    auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
    for (const auto& transceiver : transceivers) {
      if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
        return static_cast<cricket::VoiceChannel*>(
            transceiver->internal()->channel());
      }
    }
    return nullptr;
  }

  RtpTransportInternal* video_rtp_transport() {
    return (video_channel() ? video_channel()->rtp_transport() : nullptr);
  }

  cricket::VideoChannel* video_channel() {
    auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
    for (const auto& transceiver : transceivers) {
      if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
        return static_cast<cricket::VideoChannel*>(
            transceiver->internal()->channel());
      }
    }
    return nullptr;
  }

  PeerConnection* GetInternalPeerConnection() {
    auto* pci =
        static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
            pc());
    return static_cast<PeerConnection*>(pci->internal());
  }

  // Returns true if the stats indicate that an ICE connection is either in
  // progress or established with the given remote address.
  bool HasConnectionWithRemoteAddress(const SocketAddress& address) {
    auto report = GetStats();
    if (!report) {
      return false;
    }
    std::string matching_candidate_id;
    for (auto* ice_candidate_stats :
         report->GetStatsOfType<RTCRemoteIceCandidateStats>()) {
      if (*ice_candidate_stats->ip == address.HostAsURIString() &&
          *ice_candidate_stats->port == address.port()) {
        matching_candidate_id = ice_candidate_stats->id();
        break;
      }
    }
    if (matching_candidate_id.empty()) {
      return false;
    }
    for (auto* pair_stats :
         report->GetStatsOfType<RTCIceCandidatePairStats>()) {
      if (*pair_stats->remote_candidate_id == matching_candidate_id) {
        if (*pair_stats->state == RTCStatsIceCandidatePairState::kInProgress ||
            *pair_stats->state == RTCStatsIceCandidatePairState::kSucceeded) {
          return true;
        }
      }
    }
    return false;
  }

  rtc::FakeNetworkManager* network() { return network_; }

  void set_network(rtc::FakeNetworkManager* network) { network_ = network; }

 private:
  rtc::FakeNetworkManager* network_;
};

class PeerConnectionBundleBaseTest : public ::testing::Test {
 protected:
  typedef std::unique_ptr<PeerConnectionWrapperForBundleTest> WrapperPtr;

  explicit PeerConnectionBundleBaseTest(SdpSemantics sdp_semantics)
      : vss_(new rtc::VirtualSocketServer()),
        main_(vss_.get()),
        sdp_semantics_(sdp_semantics) {
#ifdef WEBRTC_ANDROID
    InitializeAndroidObjects();
#endif
    pc_factory_ = CreatePeerConnectionFactory(
        rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
        rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
        CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
        CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
        nullptr /* audio_mixer */, nullptr /* audio_processing */);
  }

  WrapperPtr CreatePeerConnection() {
    return CreatePeerConnection(RTCConfiguration());
  }

  WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
    auto* fake_network = NewFakeNetwork();
    auto port_allocator =
        std::make_unique<cricket::BasicPortAllocator>(fake_network);
    port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
                              cricket::PORTALLOCATOR_DISABLE_RELAY);
    port_allocator->set_step_delay(cricket::kMinimumStepDelay);
    auto observer = std::make_unique<MockPeerConnectionObserver>();
    RTCConfiguration modified_config = config;
    modified_config.sdp_semantics = sdp_semantics_;
    auto pc = pc_factory_->CreatePeerConnection(
        modified_config, std::move(port_allocator), nullptr, observer.get());
    if (!pc) {
      return nullptr;
    }

    auto wrapper = std::make_unique<PeerConnectionWrapperForBundleTest>(
        pc_factory_, pc, std::move(observer));
    wrapper->set_network(fake_network);
    return wrapper;
  }

  // Accepts the same arguments as CreatePeerConnection and adds default audio
  // and video tracks.
  template <typename... Args>
  WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
    auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
    if (!wrapper) {
      return nullptr;
    }
    wrapper->AddAudioTrack("a");
    wrapper->AddVideoTrack("v");
    return wrapper;
  }

  cricket::Candidate CreateLocalUdpCandidate(
      const rtc::SocketAddress& address) {
    cricket::Candidate candidate;
    candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
    candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
    candidate.set_address(address);
    candidate.set_type(cricket::LOCAL_PORT_TYPE);
    return candidate;
  }

  rtc::FakeNetworkManager* NewFakeNetwork() {
    // The PeerConnection's port allocator is tied to the PeerConnection's
    // lifetime and expects the underlying NetworkManager to outlive it. If
    // PeerConnectionWrapper owned the NetworkManager, it would be destroyed
    // before the PeerConnection (since subclass members are destroyed before
    // base class members). Therefore, the test fixture will own all the fake
    // networks even though tests should access the fake network through the
    // PeerConnectionWrapper.
    auto* fake_network = new FakeNetworkManagerWithNoAnyNetwork();
    fake_networks_.emplace_back(fake_network);
    return fake_network;
  }

  std::unique_ptr<rtc::VirtualSocketServer> vss_;
  rtc::AutoSocketServerThread main_;
  rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
  std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
  const SdpSemantics sdp_semantics_;
};

class PeerConnectionBundleTest
    : public PeerConnectionBundleBaseTest,
      public ::testing::WithParamInterface<SdpSemantics> {
 protected:
  PeerConnectionBundleTest() : PeerConnectionBundleBaseTest(GetParam()) {}
};

class PeerConnectionBundleTestUnifiedPlan
    : public PeerConnectionBundleBaseTest {
 protected:
  PeerConnectionBundleTestUnifiedPlan()
      : PeerConnectionBundleBaseTest(SdpSemantics::kUnifiedPlan) {}
};

SdpContentMutator RemoveRtcpMux() {
  return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
    content->media_description()->set_rtcp_mux(false);
  };
}

std::vector<int> GetCandidateComponents(
    const std::vector<IceCandidateInterface*> candidates) {
  std::vector<int> components;
  components.reserve(candidates.size());
  for (auto* candidate : candidates) {
    components.push_back(candidate->candidate().component());
  }
  return components;
}

// Test that there are 2 local UDP candidates (1 RTP and 1 RTCP candidate) for
// each media section when disabling bundling and disabling RTCP multiplexing.
TEST_P(PeerConnectionBundleTest,
       TwoCandidatesForEachTransportWhenNoBundleNoRtcpMux) {
  const SocketAddress kCallerAddress("1.1.1.1", 0);
  const SocketAddress kCalleeAddress("2.2.2.2", 0);

  RTCConfiguration config;
  config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  caller->network()->AddInterface(kCallerAddress);
  auto callee = CreatePeerConnectionWithAudioVideo(config);
  callee->network()->AddInterface(kCalleeAddress);

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  RTCOfferAnswerOptions options_no_bundle;
  options_no_bundle.use_rtp_mux = false;
  auto answer = callee->CreateAnswer(options_no_bundle);
  SdpContentsForEach(RemoveRtcpMux(), answer->description());
  ASSERT_TRUE(
      callee->SetLocalDescription(CloneSessionDescription(answer.get())));
  ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));

  // Check that caller has separate RTP and RTCP candidates for each media.
  EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
  EXPECT_THAT(
      GetCandidateComponents(caller->observer()->GetCandidatesByMline(0)),
      UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
                           cricket::ICE_CANDIDATE_COMPONENT_RTCP));
  EXPECT_THAT(
      GetCandidateComponents(caller->observer()->GetCandidatesByMline(1)),
      UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
                           cricket::ICE_CANDIDATE_COMPONENT_RTCP));

  // Check that callee has separate RTP and RTCP candidates for each media.
  EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kDefaultTimeout);
  EXPECT_THAT(
      GetCandidateComponents(callee->observer()->GetCandidatesByMline(0)),
      UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
                           cricket::ICE_CANDIDATE_COMPONENT_RTCP));
  EXPECT_THAT(
      GetCandidateComponents(callee->observer()->GetCandidatesByMline(1)),
      UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
                           cricket::ICE_CANDIDATE_COMPONENT_RTCP));
}

// Test that there is 1 local UDP candidate for both RTP and RTCP for each media
// section when disabling bundle but enabling RTCP multiplexing.
TEST_P(PeerConnectionBundleTest,
       OneCandidateForEachTransportWhenNoBundleButRtcpMux) {
  const SocketAddress kCallerAddress("1.1.1.1", 0);

  auto caller = CreatePeerConnectionWithAudioVideo();
  caller->network()->AddInterface(kCallerAddress);
  auto callee = CreatePeerConnectionWithAudioVideo();

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  RTCOfferAnswerOptions options_no_bundle;
  options_no_bundle.use_rtp_mux = false;
  ASSERT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswer(options_no_bundle)));

  EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);

  EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
  EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(1).size());
}

// Test that there is 1 local UDP candidate in only the first media section when
// bundling and enabling RTCP multiplexing.
TEST_P(PeerConnectionBundleTest,
       OneCandidateOnlyOnFirstTransportWhenBundleAndRtcpMux) {
  const SocketAddress kCallerAddress("1.1.1.1", 0);

  RTCConfiguration config;
  config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  caller->network()->AddInterface(kCallerAddress);
  auto callee = CreatePeerConnectionWithAudioVideo(config);

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));

  EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);

  EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
  EXPECT_EQ(0u, caller->observer()->GetCandidatesByMline(1).size());
}

// It will fail if the offerer uses the mux-BUNDLE policy but the answerer
// doesn't support BUNDLE.
TEST_P(PeerConnectionBundleTest, MaxBundleNotSupportedInAnswer) {
  RTCConfiguration config;
  config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  auto callee = CreatePeerConnectionWithAudioVideo();

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  bool equal_before =
      (caller->voice_rtp_transport() == caller->video_rtp_transport());
  EXPECT_EQ(true, equal_before);
  RTCOfferAnswerOptions options;
  options.use_rtp_mux = false;
  EXPECT_FALSE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
}

// The following parameterized test verifies that an offer/answer with varying
// bundle policies and either bundle in the answer or not will produce the
// expected RTP transports for audio and video. In particular, for bundling we
// care about whether they are separate transports or the same.

enum class BundleIncluded { kBundleInAnswer, kBundleNotInAnswer };
std::ostream& operator<<(std::ostream& out, BundleIncluded value) {
  switch (value) {
    case BundleIncluded::kBundleInAnswer:
      return out << "bundle in answer";
    case BundleIncluded::kBundleNotInAnswer:
      return out << "bundle not in answer";
  }
  return out << "unknown";
}

class PeerConnectionBundleMatrixTest
    : public PeerConnectionBundleBaseTest,
      public ::testing::WithParamInterface<
          std::tuple<SdpSemantics,
                     std::tuple<BundlePolicy, BundleIncluded, bool, bool>>> {
 protected:
  PeerConnectionBundleMatrixTest()
      : PeerConnectionBundleBaseTest(std::get<0>(GetParam())) {
    auto param = std::get<1>(GetParam());
    bundle_policy_ = std::get<0>(param);
    bundle_included_ = std::get<1>(param);
    expected_same_before_ = std::get<2>(param);
    expected_same_after_ = std::get<3>(param);
  }

  PeerConnectionInterface::BundlePolicy bundle_policy_;
  BundleIncluded bundle_included_;
  bool expected_same_before_;
  bool expected_same_after_;
};

TEST_P(PeerConnectionBundleMatrixTest,
       VerifyTransportsBeforeAndAfterSettingRemoteAnswer) {
  RTCConfiguration config;
  config.bundle_policy = bundle_policy_;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  auto callee = CreatePeerConnectionWithAudioVideo();

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  bool equal_before =
      (caller->voice_rtp_transport() == caller->video_rtp_transport());
  EXPECT_EQ(expected_same_before_, equal_before);

  RTCOfferAnswerOptions options;
  options.use_rtp_mux = (bundle_included_ == BundleIncluded::kBundleInAnswer);
  ASSERT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
  bool equal_after =
      (caller->voice_rtp_transport() == caller->video_rtp_transport());
  EXPECT_EQ(expected_same_after_, equal_after);
}

// The max-bundle policy means we should anticipate bundling being negotiated,
// and multiplex audio/video from the start.
// For all other policies, bundling should only be enabled if negotiated by the
// answer.
INSTANTIATE_TEST_SUITE_P(
    PeerConnectionBundleTest,
    PeerConnectionBundleMatrixTest,
    Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
            Values(std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
                                   BundleIncluded::kBundleInAnswer,
                                   false,
                                   true),
                   std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
                                   BundleIncluded::kBundleNotInAnswer,
                                   false,
                                   false),
                   std::make_tuple(BundlePolicy::kBundlePolicyMaxBundle,
                                   BundleIncluded::kBundleInAnswer,
                                   true,
                                   true),
                   std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
                                   BundleIncluded::kBundleInAnswer,
                                   false,
                                   true),
                   std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
                                   BundleIncluded::kBundleNotInAnswer,
                                   false,
                                   false))));

// Test that the audio/video transports on the callee side are the same before
// and after setting a local answer when max BUNDLE is enabled and an offer with
// BUNDLE is received.
TEST_P(PeerConnectionBundleTest,
       TransportsSameForMaxBundleWithBundleInRemoteOffer) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  RTCConfiguration config;
  config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
  auto callee = CreatePeerConnectionWithAudioVideo(config);

  RTCOfferAnswerOptions options_with_bundle;
  options_with_bundle.use_rtp_mux = true;
  ASSERT_TRUE(callee->SetRemoteDescription(
      caller->CreateOfferAndSetAsLocal(options_with_bundle)));

  EXPECT_EQ(callee->voice_rtp_transport(), callee->video_rtp_transport());

  ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));

  EXPECT_EQ(callee->voice_rtp_transport(), callee->video_rtp_transport());
}

TEST_P(PeerConnectionBundleTest,
       FailToSetRemoteOfferWithNoBundleWhenBundlePolicyMaxBundle) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  RTCConfiguration config;
  config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
  auto callee = CreatePeerConnectionWithAudioVideo(config);

  RTCOfferAnswerOptions options_no_bundle;
  options_no_bundle.use_rtp_mux = false;
  EXPECT_FALSE(callee->SetRemoteDescription(
      caller->CreateOfferAndSetAsLocal(options_no_bundle)));
}

// Test that if the media section which has the bundled transport is rejected,
// then the peers still connect and the bundled transport switches to the other
// media section.
// Note: This is currently failing because of the following bug:
// https://bugs.chromium.org/p/webrtc/issues/detail?id=6280
TEST_P(PeerConnectionBundleTest,
       DISABLED_SuccessfullyNegotiateMaxBundleIfBundleTransportMediaRejected) {
  RTCConfiguration config;
  config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  auto callee = CreatePeerConnection();
  callee->AddVideoTrack("v");

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));

  RTCOfferAnswerOptions options;
  options.offer_to_receive_audio = 0;
  ASSERT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));

  EXPECT_FALSE(caller->voice_rtp_transport());
  EXPECT_TRUE(caller->video_rtp_transport());
}

// When requiring RTCP multiplexing, the PeerConnection never makes RTCP
// transport channels.
TEST_P(PeerConnectionBundleTest, NeverCreateRtcpTransportWithRtcpMuxRequired) {
  RTCConfiguration config;
  config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyRequire;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  auto callee = CreatePeerConnectionWithAudioVideo();

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));

  EXPECT_FALSE(caller->voice_rtp_transport()->rtcp_mux_enabled());
  EXPECT_FALSE(caller->video_rtp_transport()->rtcp_mux_enabled());

  ASSERT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));

  EXPECT_TRUE(caller->voice_rtp_transport()->rtcp_mux_enabled());
  EXPECT_TRUE(caller->video_rtp_transport()->rtcp_mux_enabled());
}

// When negotiating RTCP multiplexing, the PeerConnection makes RTCP transports
// when the offer is sent, but will destroy them once the remote answer is set.
TEST_P(PeerConnectionBundleTest,
       CreateRtcpTransportOnlyBeforeAnswerWithRtcpMuxNegotiate) {
  RTCConfiguration config;
  config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyNegotiate;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  auto callee = CreatePeerConnectionWithAudioVideo();

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));

  EXPECT_FALSE(caller->voice_rtp_transport()->rtcp_mux_enabled());
  EXPECT_FALSE(caller->video_rtp_transport()->rtcp_mux_enabled());

  ASSERT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));

  EXPECT_TRUE(caller->voice_rtp_transport()->rtcp_mux_enabled());
  EXPECT_TRUE(caller->video_rtp_transport()->rtcp_mux_enabled());
}

TEST_P(PeerConnectionBundleTest, FailToSetDescriptionWithBundleAndNoRtcpMux) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnectionWithAudioVideo();

  RTCOfferAnswerOptions options;
  options.use_rtp_mux = true;

  auto offer = caller->CreateOffer(options);
  SdpContentsForEach(RemoveRtcpMux(), offer->description());

  std::string error;
  EXPECT_FALSE(caller->SetLocalDescription(CloneSessionDescription(offer.get()),
                                           &error));
  EXPECT_EQ(
      "Failed to set local offer sdp: rtcp-mux must be enabled when BUNDLE is "
      "enabled.",
      error);

  EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer), &error));
  EXPECT_EQ(
      "Failed to set remote offer sdp: rtcp-mux must be enabled when BUNDLE is "
      "enabled.",
      error);
}

// Test that candidates sent to the "video" transport do not get pushed down to
// the "audio" transport channel when bundling.
TEST_P(PeerConnectionBundleTest,
       IgnoreCandidatesForUnusedTransportWhenBundling) {
  const SocketAddress kAudioAddress1("1.1.1.1", 1111);
  const SocketAddress kAudioAddress2("2.2.2.2", 2222);
  const SocketAddress kVideoAddress("3.3.3.3", 3333);
  const SocketAddress kCallerAddress("4.4.4.4", 0);
  const SocketAddress kCalleeAddress("5.5.5.5", 0);

  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnectionWithAudioVideo();

  caller->network()->AddInterface(kCallerAddress);
  callee->network()->AddInterface(kCalleeAddress);

  RTCOfferAnswerOptions options;
  options.use_rtp_mux = true;

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  ASSERT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));

  // The way the *_WAIT checks work is they only wait if the condition fails,
  // which does not help in the case where state is not changing. This is
  // problematic in this test since we want to verify that adding a video
  // candidate does _not_ change state. So we interleave candidates and assume
  // that messages are executed in the order they were posted.

  cricket::Candidate audio_candidate1 = CreateLocalUdpCandidate(kAudioAddress1);
  ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate1,
                                             cricket::MEDIA_TYPE_AUDIO));

  cricket::Candidate video_candidate = CreateLocalUdpCandidate(kVideoAddress);
  ASSERT_TRUE(caller->AddIceCandidateToMedia(&video_candidate,
                                             cricket::MEDIA_TYPE_VIDEO));

  cricket::Candidate audio_candidate2 = CreateLocalUdpCandidate(kAudioAddress2);
  ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate2,
                                             cricket::MEDIA_TYPE_AUDIO));

  EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress1),
                   kDefaultTimeout);
  EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress2),
                   kDefaultTimeout);
  EXPECT_FALSE(caller->HasConnectionWithRemoteAddress(kVideoAddress));
}

// Test that the transport used by both audio and video is the transport
// associated with the first MID in the answer BUNDLE group, even if it's in a
// different order from the offer.
TEST_P(PeerConnectionBundleTest, BundleOnFirstMidInAnswer) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnectionWithAudioVideo();

  ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));

  auto* old_video_transport = caller->video_rtp_transport();

  auto answer = callee->CreateAnswer();
  auto* old_bundle_group =
      answer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  std::string first_mid = old_bundle_group->content_names()[0];
  std::string second_mid = old_bundle_group->content_names()[1];
  answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);

  cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
  new_bundle_group.AddContentName(second_mid);
  new_bundle_group.AddContentName(first_mid);
  answer->description()->AddGroup(new_bundle_group);

  ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));

  EXPECT_EQ(old_video_transport, caller->video_rtp_transport());
  EXPECT_EQ(caller->voice_rtp_transport(), caller->video_rtp_transport());
}

// This tests that applying description with conflicted RTP demuxing criteria
// will fail.
TEST_P(PeerConnectionBundleTest,
       ApplyDescriptionWithConflictedDemuxCriteriaFail) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnectionWithAudioVideo();

  RTCOfferAnswerOptions options;
  options.use_rtp_mux = false;
  auto offer = caller->CreateOffer(options);
  // Modified the SDP to make two m= sections have the same SSRC.
  ASSERT_GE(offer->description()->contents().size(), 2U);
  offer->description()
      ->contents()[0]
      .media_description()
      ->mutable_streams()[0]
      .ssrcs[0] = 1111222;
  offer->description()
      ->contents()[1]
      .media_description()
      ->mutable_streams()[0]
      .ssrcs[0] = 1111222;
  EXPECT_TRUE(
      caller->SetLocalDescription(CloneSessionDescription(offer.get())));
  EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
  EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal(options));

  // Enable BUNDLE in subsequent offer/answer exchange and two m= sections are
  // expectd to use one RtpTransport underneath.
  options.use_rtp_mux = true;
  EXPECT_TRUE(
      callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
  auto answer = callee->CreateAnswer(options);
  // When BUNDLE is enabled, applying the description is expected to fail
  // because the demuxing criteria is conflicted.
  EXPECT_FALSE(callee->SetLocalDescription(std::move(answer)));
}

// This tests that changing the pre-negotiated BUNDLE tag is not supported.
TEST_P(PeerConnectionBundleTest, RejectDescriptionChangingBundleTag) {
  RTCConfiguration config;
  config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  auto callee = CreatePeerConnectionWithAudioVideo(config);

  RTCOfferAnswerOptions options;
  options.use_rtp_mux = true;
  auto offer = caller->CreateOfferAndSetAsLocal(options);

  // Create a new bundle-group with different bundled_mid.
  auto* old_bundle_group =
      offer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  std::string first_mid = old_bundle_group->content_names()[0];
  std::string second_mid = old_bundle_group->content_names()[1];
  cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
  new_bundle_group.AddContentName(second_mid);

  auto re_offer = CloneSessionDescription(offer.get());
  callee->SetRemoteDescription(std::move(offer));
  auto answer = callee->CreateAnswer(options);
  // Reject the first MID.
  answer->description()->contents()[0].rejected = true;
  // Remove the first MID from the bundle group.
  answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  answer->description()->AddGroup(new_bundle_group);
  // The answer is expected to be rejected.
  EXPECT_FALSE(caller->SetRemoteDescription(std::move(answer)));

  // Do the same thing for re-offer.
  re_offer->description()->contents()[0].rejected = true;
  re_offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  re_offer->description()->AddGroup(new_bundle_group);
  // The re-offer is expected to be rejected.
  EXPECT_FALSE(caller->SetLocalDescription(std::move(re_offer)));
}

// This tests that removing contents from BUNDLE group and reject the whole
// BUNDLE group could work. This is a regression test for
// (https://bugs.chromium.org/p/chromium/issues/detail?id=827917)
TEST_P(PeerConnectionBundleTest, RemovingContentAndRejectBundleGroup) {
  RTCConfiguration config;
#ifndef HAVE_SCTP
  config.enable_rtp_data_channel = true;
#endif
  config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
  auto caller = CreatePeerConnectionWithAudioVideo(config);
  caller->CreateDataChannel("dc");

  auto offer = caller->CreateOfferAndSetAsLocal();
  auto re_offer = CloneSessionDescription(offer.get());

  // Removing the second MID from the BUNDLE group.
  auto* old_bundle_group =
      offer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  std::string first_mid = old_bundle_group->content_names()[0];
  std::string third_mid = old_bundle_group->content_names()[2];
  cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
  new_bundle_group.AddContentName(first_mid);
  new_bundle_group.AddContentName(third_mid);

  // Reject the entire new bundle group.
  re_offer->description()->contents()[0].rejected = true;
  re_offer->description()->contents()[2].rejected = true;
  re_offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  re_offer->description()->AddGroup(new_bundle_group);

  EXPECT_TRUE(caller->SetLocalDescription(std::move(re_offer)));
}

// This tests that the BUNDLE group in answer should be a subset of the offered
// group.
TEST_P(PeerConnectionBundleTest, AddContentToBundleGroupInAnswerNotSupported) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnectionWithAudioVideo();

  auto offer = caller->CreateOffer();
  std::string first_mid = offer->description()->contents()[0].name;
  std::string second_mid = offer->description()->contents()[1].name;

  cricket::ContentGroup bundle_group(cricket::GROUP_TYPE_BUNDLE);
  bundle_group.AddContentName(first_mid);
  offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  offer->description()->AddGroup(bundle_group);
  EXPECT_TRUE(
      caller->SetLocalDescription(CloneSessionDescription(offer.get())));
  EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));

  auto answer = callee->CreateAnswer();
  bundle_group.AddContentName(second_mid);
  answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  answer->description()->AddGroup(bundle_group);

  // The answer is expected to be rejected because second mid is not in the
  // offered BUNDLE group.
  EXPECT_FALSE(callee->SetLocalDescription(std::move(answer)));
}

// This tests that the BUNDLE group with non-existing MID should be rejectd.
TEST_P(PeerConnectionBundleTest, RejectBundleGroupWithNonExistingMid) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnectionWithAudioVideo();

  auto offer = caller->CreateOffer();
  auto invalid_bundle_group =
      *offer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  invalid_bundle_group.AddContentName("non-existing-MID");
  offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  offer->description()->AddGroup(invalid_bundle_group);

  EXPECT_FALSE(
      caller->SetLocalDescription(CloneSessionDescription(offer.get())));
  EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
}

// This tests that an answer shouldn't be able to remove an m= section from an
// established group without rejecting it.
TEST_P(PeerConnectionBundleTest, RemoveContentFromBundleGroup) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnectionWithAudioVideo();

  EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  EXPECT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));

  EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
  auto answer = callee->CreateAnswer();
  std::string second_mid = answer->description()->contents()[1].name;

  auto invalid_bundle_group =
      *answer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  invalid_bundle_group.RemoveContentName(second_mid);
  answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  answer->description()->AddGroup(invalid_bundle_group);

  EXPECT_FALSE(
      callee->SetLocalDescription(CloneSessionDescription(answer.get())));
}

INSTANTIATE_TEST_SUITE_P(PeerConnectionBundleTest,
                         PeerConnectionBundleTest,
                         Values(SdpSemantics::kPlanB,
                                SdpSemantics::kUnifiedPlan));

// According to RFC5888, if an endpoint understands the semantics of an
// "a=group", it MUST return an answer with that group. So, an empty BUNDLE
// group is valid when the answerer rejects all m= sections (by stopping all
// transceivers), meaning there's nothing to bundle.
//
// Only writing this test for Unified Plan mode, since there's no way to reject
// m= sections in answers for Plan B without SDP munging.
TEST_F(PeerConnectionBundleTestUnifiedPlan,
       EmptyBundleGroupCreatedInAnswerWhenAppropriate) {
  auto caller = CreatePeerConnectionWithAudioVideo();
  auto callee = CreatePeerConnection();

  EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));

  // Stop all transceivers, causing all m= sections to be rejected.
  for (const auto& transceiver : callee->pc()->GetTransceivers()) {
    transceiver->StopInternal();
  }
  EXPECT_TRUE(
      caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));

  // Verify that the answer actually contained an empty bundle group.
  const SessionDescriptionInterface* desc = callee->pc()->local_description();
  ASSERT_NE(nullptr, desc);
  const cricket::ContentGroup* bundle_group =
      desc->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  ASSERT_NE(nullptr, bundle_group);
  EXPECT_TRUE(bundle_group->content_names().empty());
}

}  // namespace webrtc
