/*
 *  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/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_proxy.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)
#ifdef HAVE_SCTP
TEST_P(PeerConnectionBundleTest, RemovingContentAndRejectBundleGroup) {
  RTCConfiguration config;
  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)));
}
#endif

// 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());
}

TEST_F(PeerConnectionBundleTestUnifiedPlan, MultipleBundleGroups) {
  auto caller = CreatePeerConnection();
  caller->AddAudioTrack("0_audio");
  caller->AddAudioTrack("1_audio");
  caller->AddVideoTrack("2_audio");
  caller->AddVideoTrack("3_audio");
  auto callee = CreatePeerConnection();

  auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
  // Modify the GROUP to have two BUNDLEs. We know that the MIDs will be 0,1,2,4
  // because our implementation has predictable MIDs.
  offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  cricket::ContentGroup bundle_group1(cricket::GROUP_TYPE_BUNDLE);
  bundle_group1.AddContentName("0");
  bundle_group1.AddContentName("1");
  cricket::ContentGroup bundle_group2(cricket::GROUP_TYPE_BUNDLE);
  bundle_group2.AddContentName("2");
  bundle_group2.AddContentName("3");
  offer->description()->AddGroup(bundle_group1);
  offer->description()->AddGroup(bundle_group2);

  EXPECT_TRUE(
      caller->SetLocalDescription(CloneSessionDescription(offer.get())));
  EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
  auto answer = callee->CreateAnswer();
  EXPECT_TRUE(
      callee->SetLocalDescription(CloneSessionDescription(answer.get())));
  EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));

  // Verify bundling on sender side.
  auto senders = caller->pc()->GetSenders();
  ASSERT_EQ(senders.size(), 4u);
  auto sender0_transport = senders[0]->dtls_transport();
  auto sender1_transport = senders[1]->dtls_transport();
  auto sender2_transport = senders[2]->dtls_transport();
  auto sender3_transport = senders[3]->dtls_transport();
  EXPECT_EQ(sender0_transport, sender1_transport);
  EXPECT_EQ(sender2_transport, sender3_transport);
  EXPECT_NE(sender0_transport, sender2_transport);

  // Verify bundling on receiver side.
  auto receivers = callee->pc()->GetReceivers();
  ASSERT_EQ(receivers.size(), 4u);
  auto receiver0_transport = receivers[0]->dtls_transport();
  auto receiver1_transport = receivers[1]->dtls_transport();
  auto receiver2_transport = receivers[2]->dtls_transport();
  auto receiver3_transport = receivers[3]->dtls_transport();
  EXPECT_EQ(receiver0_transport, receiver1_transport);
  EXPECT_EQ(receiver2_transport, receiver3_transport);
  EXPECT_NE(receiver0_transport, receiver2_transport);
}

// Test that, with the "max-compat" bundle policy, it's possible to add an m=
// section that's not part of an existing bundle group.
TEST_F(PeerConnectionBundleTestUnifiedPlan, AddNonBundledSection) {
  RTCConfiguration config;
  config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxCompat;
  auto caller = CreatePeerConnection(config);
  caller->AddAudioTrack("0_audio");
  caller->AddAudioTrack("1_audio");
  auto callee = CreatePeerConnection(config);

  // Establish an existing BUNDLE group.
  auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
  EXPECT_TRUE(
      caller->SetLocalDescription(CloneSessionDescription(offer.get())));
  EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
  auto answer = callee->CreateAnswer();
  EXPECT_TRUE(
      callee->SetLocalDescription(CloneSessionDescription(answer.get())));
  EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));

  // Add a track but munge SDP so it's not part of the bundle group.
  caller->AddAudioTrack("3_audio");
  offer = caller->CreateOffer(RTCOfferAnswerOptions());
  offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
  cricket::ContentGroup bundle_group(cricket::GROUP_TYPE_BUNDLE);
  bundle_group.AddContentName("0");
  bundle_group.AddContentName("1");
  offer->description()->AddGroup(bundle_group);
  EXPECT_TRUE(
      caller->SetLocalDescription(CloneSessionDescription(offer.get())));
  EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
  answer = callee->CreateAnswer();
  EXPECT_TRUE(
      callee->SetLocalDescription(CloneSessionDescription(answer.get())));
  EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));

  // Verify bundling on the sender side.
  auto senders = caller->pc()->GetSenders();
  ASSERT_EQ(senders.size(), 3u);
  auto sender0_transport = senders[0]->dtls_transport();
  auto sender1_transport = senders[1]->dtls_transport();
  auto sender2_transport = senders[2]->dtls_transport();
  EXPECT_EQ(sender0_transport, sender1_transport);
  EXPECT_NE(sender0_transport, sender2_transport);

  // Verify bundling on receiver side.
  auto receivers = callee->pc()->GetReceivers();
  ASSERT_EQ(receivers.size(), 3u);
  auto receiver0_transport = receivers[0]->dtls_transport();
  auto receiver1_transport = receivers[1]->dtls_transport();
  auto receiver2_transport = receivers[2]->dtls_transport();
  EXPECT_EQ(receiver0_transport, receiver1_transport);
  EXPECT_NE(receiver0_transport, receiver2_transport);
}

}  // namespace webrtc
