/*
 *  Copyright (c) 2022 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.
 */

// This file contains tests that verify that field trials do what they're
// supposed to do.

#include <set>

#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_interface.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "media/engine/webrtc_media_engine.h"
#include "media/engine/webrtc_media_engine_defaults.h"
#include "pc/peer_connection_wrapper.h"
#include "pc/session_description.h"
#include "pc/test/fake_audio_capture_module.h"
#include "pc/test/peer_connection_test_wrapper.h"
#include "rtc_base/internal/default_socket_server.h"
#include "rtc_base/physical_socket_server.h"
#include "rtc_base/thread.h"
#include "test/gtest.h"
#include "test/scoped_key_value_config.h"

namespace webrtc {

using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;

class PeerConnectionFieldTrialTest : public ::testing::Test {
 protected:
  typedef std::unique_ptr<PeerConnectionWrapper> WrapperPtr;

  PeerConnectionFieldTrialTest()
      : socket_server_(rtc::CreateDefaultSocketServer()),
        main_thread_(socket_server_.get()) {
    webrtc::PeerConnectionInterface::IceServer ice_server;
    ice_server.uri = "stun:stun.l.google.com:19302";
    config_.servers.push_back(ice_server);
    config_.sdp_semantics = SdpSemantics::kUnifiedPlan;
  }

  void TearDown() override { pc_factory_ = nullptr; }

  void CreatePCFactory(std::unique_ptr<FieldTrialsView> field_trials) {
    PeerConnectionFactoryDependencies pcf_deps;
    pcf_deps.signaling_thread = rtc::Thread::Current();
    pcf_deps.worker_thread = rtc::Thread::Current();
    pcf_deps.network_thread = rtc::Thread::Current();
    pcf_deps.trials = std::move(field_trials);
    pcf_deps.task_queue_factory = CreateDefaultTaskQueueFactory();
    pcf_deps.call_factory = webrtc::CreateCallFactory();
    cricket::MediaEngineDependencies media_deps;
    media_deps.task_queue_factory = pcf_deps.task_queue_factory.get();
    media_deps.adm = FakeAudioCaptureModule::Create();
    media_deps.trials = pcf_deps.trials.get();
    webrtc::SetMediaEngineDefaults(&media_deps);
    pcf_deps.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
    pc_factory_ = CreateModularPeerConnectionFactory(std::move(pcf_deps));
  }

  WrapperPtr CreatePeerConnection() {
    auto observer = std::make_unique<MockPeerConnectionObserver>();
    auto result = pc_factory_->CreatePeerConnectionOrError(
        config_, PeerConnectionDependencies(observer.get()));
    RTC_CHECK(result.ok());

    observer->SetPeerConnectionInterface(result.value().get());
    return std::make_unique<PeerConnectionWrapper>(
        pc_factory_, result.MoveValue(), std::move(observer));
  }

  std::unique_ptr<rtc::SocketServer> socket_server_;
  rtc::AutoSocketServerThread main_thread_;
  rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
  webrtc::PeerConnectionInterface::RTCConfiguration config_;
};

// Tests for the dependency descriptor field trial. The dependency descriptor
// field trial is implemented in media/engine/webrtc_video_engine.cc.
TEST_F(PeerConnectionFieldTrialTest, EnableDependencyDescriptorAdvertised) {
  std::unique_ptr<test::ScopedKeyValueConfig> field_trials =
      std::make_unique<test::ScopedKeyValueConfig>(
          "WebRTC-DependencyDescriptorAdvertised/Enabled/");
  CreatePCFactory(std::move(field_trials));

  WrapperPtr caller = CreatePeerConnection();
  caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);

  auto offer = caller->CreateOffer();
  auto contents1 = offer->description()->contents();
  ASSERT_EQ(1u, contents1.size());

  const cricket::MediaContentDescription* media_description1 =
      contents1[0].media_description();
  EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, media_description1->type());
  const cricket::RtpHeaderExtensions& rtp_header_extensions1 =
      media_description1->rtp_header_extensions();

  bool found = absl::c_find_if(rtp_header_extensions1,
                               [](const webrtc::RtpExtension& rtp_extension) {
                                 return rtp_extension.uri ==
                                        RtpExtension::kDependencyDescriptorUri;
                               }) != rtp_header_extensions1.end();
  EXPECT_TRUE(found);
}

// Tests that dependency descriptor RTP header extensions can be exchanged
// via SDP munging, even if dependency descriptor field trial is disabled.
TEST_F(PeerConnectionFieldTrialTest, InjectDependencyDescriptor) {
  std::unique_ptr<test::ScopedKeyValueConfig> field_trials =
      std::make_unique<test::ScopedKeyValueConfig>(
          "WebRTC-DependencyDescriptorAdvertised/Disabled/");
  CreatePCFactory(std::move(field_trials));

  WrapperPtr caller = CreatePeerConnection();
  WrapperPtr callee = CreatePeerConnection();
  caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);

  auto offer = caller->CreateOffer();
  cricket::ContentInfos& contents1 = offer->description()->contents();
  ASSERT_EQ(1u, contents1.size());

  cricket::MediaContentDescription* media_description1 =
      contents1[0].media_description();
  EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, media_description1->type());
  cricket::RtpHeaderExtensions rtp_header_extensions1 =
      media_description1->rtp_header_extensions();

  bool found1 = absl::c_find_if(rtp_header_extensions1,
                                [](const webrtc::RtpExtension& rtp_extension) {
                                  return rtp_extension.uri ==
                                         RtpExtension::kDependencyDescriptorUri;
                                }) != rtp_header_extensions1.end();
  EXPECT_FALSE(found1);

  std::set<int> existing_ids;
  for (const webrtc::RtpExtension& rtp_extension : rtp_header_extensions1) {
    existing_ids.insert(rtp_extension.id);
  }

  // Find the currently unused RTP header extension ID.
  int insert_id = 1;
  std::set<int>::const_iterator iter = existing_ids.begin();
  while (true) {
    if (iter == existing_ids.end()) {
      break;
    }
    if (*iter != insert_id) {
      break;
    }
    insert_id++;
    iter++;
  }

  rtp_header_extensions1.emplace_back(RtpExtension::kDependencyDescriptorUri,
                                      insert_id);
  media_description1->set_rtp_header_extensions(rtp_header_extensions1);

  caller->SetLocalDescription(offer->Clone());

  ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
  auto answer = callee->CreateAnswer();

  cricket::ContentInfos& contents2 = answer->description()->contents();
  ASSERT_EQ(1u, contents2.size());

  cricket::MediaContentDescription* media_description2 =
      contents2[0].media_description();
  EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, media_description2->type());
  cricket::RtpHeaderExtensions rtp_header_extensions2 =
      media_description2->rtp_header_extensions();

  bool found2 = absl::c_find_if(rtp_header_extensions2,
                                [](const webrtc::RtpExtension& rtp_extension) {
                                  return rtp_extension.uri ==
                                         RtpExtension::kDependencyDescriptorUri;
                                }) != rtp_header_extensions2.end();
  EXPECT_TRUE(found2);
}

}  // namespace webrtc
