/*
 *  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 "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 "absl/memory/memory.h"
#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;
  }

  rtc::PacketTransportInternal* voice_rtp_transport() {
    return (voice_channel() ? voice_channel()->rtp_packet_transport()
                            : nullptr);
  }

  rtc::PacketTransportInternal* voice_rtcp_transport() {
    return (voice_channel() ? voice_channel()->rtcp_packet_transport()
                            : nullptr);
  }

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

  rtc::PacketTransportInternal* video_rtp_transport() {
    return (video_channel() ? video_channel()->rtp_packet_transport()
                            : nullptr);
  }

  rtc::PacketTransportInternal* video_rtcp_transport() {
    return (video_channel() ? video_channel()->rtcp_packet_transport()
                            : nullptr);
  }

  cricket::VideoChannel* video_channel() {
    auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
    for (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 =
        absl::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 = absl::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 = absl::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;
  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_CASE_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_rtcp_transport());
  EXPECT_FALSE(caller->video_rtcp_transport());

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

  EXPECT_FALSE(caller->voice_rtcp_transport());
  EXPECT_FALSE(caller->video_rtcp_transport());
}

// 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_TRUE(caller->voice_rtcp_transport());
  EXPECT_TRUE(caller->video_rtcp_transport());

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

  EXPECT_FALSE(caller->voice_rtcp_transport());
  EXPECT_FALSE(caller->video_rtcp_transport());
}

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]
      .description->mutable_streams()[0]
      .ssrcs[0] = 1111222;
  offer->description()
      ->contents()[1]
      .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_CASE_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->Stop();
  }
  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
