/*
 *  Copyright 2012 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 "pc/test/integration_test_helpers.h"

#include <algorithm>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "api/audio/builtin_audio_processing_builder.h"
#include "api/audio_options.h"
#include "api/candidate.h"
#include "api/create_modular_peer_connection_factory.h"
#include "api/crypto/crypto_options.h"
#include "api/data_channel_interface.h"
#include "api/dtls_transport_interface.h"
#include "api/enable_media_with_defaults.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "api/jsep.h"
#include "api/make_ref_counted.h"
#include "api/media_stream_interface.h"
#include "api/media_types.h"
#include "api/payload_type.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
#include "api/rtp_parameters.h"
#include "api/rtp_receiver_interface.h"
#include "api/rtp_sender_interface.h"
#include "api/rtp_transceiver_direction.h"
#include "api/rtp_transceiver_interface.h"
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/stats/rtc_stats_report.h"
#include "api/stats/rtcstats_objects.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "api/test/rtc_error_matchers.h"
#include "api/test/time_controller.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "api/video/video_rotation.h"
#include "logging/rtc_event_log/fake_rtc_event_log_factory.h"
#include "media/base/codec.h"
#include "media/base/stream_params.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/port.h"
#include "p2p/test/test_turn_customizer.h"
#include "p2p/test/test_turn_server.h"
#include "pc/peer_connection.h"
#include "pc/peer_connection_factory.h"
#include "pc/peer_connection_proxy.h"
#include "pc/session_description.h"
#include "pc/test/fake_audio_capture_module.h"
#include "pc/test/fake_periodic_video_source.h"
#include "pc/test/fake_periodic_video_track_source.h"
#include "pc/test/fake_rtc_certificate_generator.h"
#include "pc/test/fake_video_track_renderer.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "pc/test/rtc_stats_obtainer.h"
#include "rtc_base/checks.h"
#include "rtc_base/containers/flat_map.h"
#include "rtc_base/crypto_random.h"
#include "rtc_base/fake_mdns_responder.h"
#include "rtc_base/fake_network.h"
#include "rtc_base/firewall_socket_server.h"
#include "rtc_base/logging.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/socket_factory.h"
#include "rtc_base/socket_server.h"
#include "rtc_base/ssl_stream_adapter.h"
#include "rtc_base/task_queue_for_test.h"
#include "rtc_base/thread.h"
#include "rtc_base/virtual_socket_server.h"
#include "system_wrappers/include/metrics.h"
#include "test/create_test_environment.h"
#include "test/create_test_field_trials.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/run_loop.h"
#include "test/time_controller/simulated_time_controller.h"
#include "test/wait_until.h"

namespace webrtc {

using testing::NotNull;

PeerConnectionInterface::RTCOfferAnswerOptions IceRestartOfferAnswerOptions() {
  PeerConnectionInterface::RTCOfferAnswerOptions options;
  options.ice_restart = true;
  return options;
}

void RemoveSsrcsAndMsids(std::unique_ptr<SessionDescriptionInterface>& sdp) {
  for (ContentInfo& content : sdp->description()->contents()) {
    content.media_description()->mutable_streams().clear();
  }
  sdp->description()->set_msid_signaling(0);
}

void RemoveSsrcsAndKeepMsids(
    std::unique_ptr<SessionDescriptionInterface>& sdp) {
  for (ContentInfo& content : sdp->description()->contents()) {
    std::string track_id;
    std::vector<std::string> stream_ids;
    if (!content.media_description()->streams().empty()) {
      const StreamParams& first_stream =
          content.media_description()->streams()[0];
      track_id = first_stream.id;
      stream_ids = first_stream.stream_ids();
    }
    content.media_description()->mutable_streams().clear();
    StreamParams new_stream;
    new_stream.id = track_id;
    new_stream.set_stream_ids(stream_ids);
    content.media_description()->AddStream(new_stream);
  }
}

void SetSdpType(std::unique_ptr<SessionDescriptionInterface>& sdp,
                SdpType sdpType) {
  std::string str;
  sdp->ToString(&str);
  sdp = CreateSessionDescription(sdpType, str);
}

void ReplaceFirstSsrc(StreamParams& stream, uint32_t ssrc) {
  stream.ssrcs[0] = ssrc;
  for (auto& group : stream.ssrc_groups) {
    group.ssrcs[0] = ssrc;
  }
}

int FindFirstMediaStatsIndexByKind(
    const std::string& kind,
    const std::vector<const RTCInboundRtpStreamStats*>& inbound_rtps) {
  for (size_t i = 0; i < inbound_rtps.size(); i++) {
    if (*inbound_rtps[i]->kind == kind) {
      return i;
    }
  }
  return -1;
}

TaskQueueMetronome::TaskQueueMetronome(TimeDelta tick_period)
    : tick_period_(tick_period) {}

TaskQueueMetronome::~TaskQueueMetronome() {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
}
void TaskQueueMetronome::RequestCallOnNextTick(
    absl::AnyInvocable<void() &&> callback) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  callbacks_.push_back(std::move(callback));
  // Only schedule a tick callback for the first `callback` addition.
  // Schedule on the current task queue to comply with RequestCallOnNextTick
  // requirements.
  if (callbacks_.size() == 1) {
    TaskQueueBase::Current()->PostDelayedTask(
        SafeTask(safety_.flag(),
                 [this] {
                   RTC_DCHECK_RUN_ON(&sequence_checker_);
                   std::vector<absl::AnyInvocable<void() &&>> callbacks;
                   callbacks.swap(callbacks_);
                   for (auto& callback : callbacks)
                     std::move(callback)();
                 }),
        tick_period_);
  }
}

TimeDelta TaskQueueMetronome::TickPeriod() const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  return tick_period_;
}

PeerConnectionIntegrationWrapper::PeerConnectionIntegrationWrapper(
    const std::string& debug_name,
    Environment env,
    internal::PeerConnectionIntegrationTestBase* test)
    : debug_name_(debug_name), env_(env), test_(test) {}

PeerConnection* PeerConnectionIntegrationWrapper::pc_internal() const {
  auto* pci =
      static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
          pc());
  return static_cast<PeerConnection*>(pci->internal());
}

void PeerConnectionIntegrationWrapper::CreateAndSetAndSignalOffer() {
  std::unique_ptr<SessionDescriptionInterface> offer = CreateOfferAndWait();
  ASSERT_NE(nullptr, offer);
  EXPECT_TRUE(SetLocalDescriptionAndSendSdpMessage(std::move(offer)));
}

void PeerConnectionIntegrationWrapper::AddAudioVideoTracks() {
  AddAudioTrack();
  AddVideoTrack();
  ResetRtpSenderObservers();
}

scoped_refptr<AudioTrackInterface>
PeerConnectionIntegrationWrapper::CreateLocalAudioTrack() {
  AudioOptions options;
  // Disable highpass filter so that we can get all the test audio frames.
  options.highpass_filter = false;
  scoped_refptr<AudioSourceInterface> source =
      peer_connection_factory_->CreateAudioSource(options);
  // TODO(perkj): Test audio source when it is implemented. Currently audio
  // always use the default input.
  return peer_connection_factory_->CreateAudioTrack(CreateRandomUuid(),
                                                    source.get());
}

scoped_refptr<VideoTrackInterface>
PeerConnectionIntegrationWrapper::CreateLocalVideoTrack() {
  FakePeriodicVideoSource::Config config;
  config.timestamp_offset = env_.clock().CurrentTime();
  return CreateLocalVideoTrackInternal(config);
}

scoped_refptr<VideoTrackInterface>
PeerConnectionIntegrationWrapper::CreateLocalVideoTrackWithConfig(
    FakePeriodicVideoSource::Config config) {
  return CreateLocalVideoTrackInternal(config);
}

scoped_refptr<VideoTrackInterface>
PeerConnectionIntegrationWrapper::CreateLocalVideoTrackWithRotation(
    VideoRotation rotation) {
  FakePeriodicVideoSource::Config config;
  config.rotation = rotation;
  config.timestamp_offset = env_.clock().CurrentTime();
  return CreateLocalVideoTrackInternal(config);
}

scoped_refptr<RtpSenderInterface> PeerConnectionIntegrationWrapper::AddTrack(
    scoped_refptr<MediaStreamTrackInterface> track,
    const std::vector<std::string>& stream_ids) {
  EXPECT_TRUE(track);
  if (!track) {
    return nullptr;
  }
  auto result = pc()->AddTrack(track, stream_ids);
  EXPECT_EQ(RTCErrorType::NONE, result.error().type());
  if (result.ok()) {
    return result.MoveValue();
  } else {
    return nullptr;
  }
}

std::vector<scoped_refptr<RtpReceiverInterface>>
PeerConnectionIntegrationWrapper::GetReceiversOfType(
    webrtc::MediaType media_type) {
  std::vector<scoped_refptr<RtpReceiverInterface>> receivers;
  for (const auto& receiver : pc()->GetReceivers()) {
    if (receiver->media_type() == media_type) {
      receivers.push_back(receiver);
    }
  }
  return receivers;
}

scoped_refptr<RtpTransceiverInterface>
PeerConnectionIntegrationWrapper::GetFirstTransceiverOfType(
    webrtc::MediaType media_type) {
  for (auto transceiver : pc()->GetTransceivers()) {
    if (transceiver->receiver()->media_type() == media_type) {
      return transceiver;
    }
  }
  return nullptr;
}

bool PeerConnectionIntegrationWrapper::SignalingStateStable() {
  return pc()->signaling_state() == PeerConnectionInterface::kStable;
}

bool PeerConnectionIntegrationWrapper::IceGatheringStateComplete() {
  return pc()->ice_gathering_state() ==
         PeerConnectionInterface::kIceGatheringComplete;
}

void PeerConnectionIntegrationWrapper::CreateDataChannel() {
  CreateDataChannel(nullptr);
}

void PeerConnectionIntegrationWrapper::CreateDataChannel(
    const DataChannelInit* init) {
  CreateDataChannel(kDataChannelLabel, init);
}

void PeerConnectionIntegrationWrapper::CreateDataChannel(
    const std::string& label,
    const DataChannelInit* init) {
  auto data_channel_or_error = pc()->CreateDataChannelOrError(label, init);
  ASSERT_TRUE(data_channel_or_error.ok());
  data_channels_.push_back(data_channel_or_error.MoveValue());
  ASSERT_TRUE(data_channels_.back().get() != nullptr);
  data_observers_.push_back(
      std::make_unique<MockDataChannelObserver>(data_channels_.back().get()));
}

DataChannelInterface* PeerConnectionIntegrationWrapper::data_channel() {
  if (data_channels_.empty()) {
    return nullptr;
  }
  return data_channels_.back().get();
}

MockDataChannelObserver* PeerConnectionIntegrationWrapper::data_observer()
    const {
  if (data_observers_.empty()) {
    return nullptr;
  }
  return data_observers_.back().get();
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionIntegrationWrapper::CreateAnswerForTest() {
  return CreateAnswer();
}

int PeerConnectionIntegrationWrapper::audio_frames_received() const {
  return fake_audio_capture_module_->frames_received();
}

int PeerConnectionIntegrationWrapper::min_video_frames_received_per_track()
    const {
  int min_frames = INT_MAX;
  if (fake_video_renderers_.empty()) {
    return 0;
  }

  for (const auto& pair : fake_video_renderers_) {
    min_frames = std::min(min_frames, pair.second->num_rendered_frames());
  }
  return min_frames;
}

scoped_refptr<MockStatsObserver>
PeerConnectionIntegrationWrapper::OldGetStatsForTrack(
    MediaStreamTrackInterface* track) {
  auto observer = make_ref_counted<MockStatsObserver>();
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
  EXPECT_TRUE(peer_connection_->GetStats(
      observer.get(), nullptr,
      PeerConnectionInterface::kStatsOutputLevelStandard));
#pragma clang diagnostic pop
  EXPECT_THAT(test_->GetWaiter().Until([&] { return observer->called(); },
                                       ::testing::IsTrue()),
              IsRtcOk());
  return observer;
}

scoped_refptr<MockStatsObserver>
PeerConnectionIntegrationWrapper::OldGetStats() {
  return OldGetStatsForTrack(nullptr);
}

scoped_refptr<const RTCStatsReport>
PeerConnectionIntegrationWrapper::NewGetStats(WaitUntilSettings settings) {
  auto callback = make_ref_counted<MockRTCStatsCollectorCallback>();
  peer_connection_->GetStats(callback.get());
  EXPECT_THAT(test_->GetWaiter(settings).Until(
                  [&] { return callback->called(); }, ::testing::IsTrue()),
              IsRtcOk());
  return callback->report();
}

scoped_refptr<const RTCStatsReport>
PeerConnectionIntegrationWrapper::NewGetStats(test::RunLoop& run_loop) {
  scoped_refptr<const RTCStatsReport> report;
  auto callback = RTCStatsObtainer::Create(&report, run_loop.QuitClosure());
  peer_connection_->GetStats(callback.get());
  run_loop.Run();
  EXPECT_TRUE(report);
  return report;
}

std::string PeerConnectionIntegrationWrapper::DtlsCipher() {
  auto report = NewGetStats();
  if (!report)
    return "";
  auto stats = report->GetStatsOfType<RTCTransportStats>();
  if (stats.empty() || !stats[0]->dtls_cipher.has_value())
    return "";
  return *stats[0]->dtls_cipher;
}

std::string PeerConnectionIntegrationWrapper::SrtpCipher() {
  auto report = NewGetStats();
  if (!report)
    return "";
  auto stats = report->GetStatsOfType<RTCTransportStats>();
  if (stats.empty() || !stats[0]->srtp_cipher.has_value())
    return "";
  return *stats[0]->srtp_cipher;
}

int PeerConnectionIntegrationWrapper::rendered_width() {
  EXPECT_FALSE(fake_video_renderers_.empty());
  return fake_video_renderers_.empty()
             ? 0
             : fake_video_renderers_.begin()->second->width();
}

int PeerConnectionIntegrationWrapper::rendered_height() {
  EXPECT_FALSE(fake_video_renderers_.empty());
  return fake_video_renderers_.empty()
             ? 0
             : fake_video_renderers_.begin()->second->height();
}

double PeerConnectionIntegrationWrapper::rendered_aspect_ratio() {
  if (rendered_height() == 0) {
    return 0.0;
  }
  return static_cast<double>(rendered_width()) / rendered_height();
}

VideoRotation PeerConnectionIntegrationWrapper::rendered_rotation() {
  EXPECT_FALSE(fake_video_renderers_.empty());
  return fake_video_renderers_.empty()
             ? kVideoRotation_0
             : fake_video_renderers_.begin()->second->rotation();
}

int PeerConnectionIntegrationWrapper::local_rendered_width() {
  return local_video_renderer_ ? local_video_renderer_->width() : 0;
}

int PeerConnectionIntegrationWrapper::local_rendered_height() {
  return local_video_renderer_ ? local_video_renderer_->height() : 0;
}

double PeerConnectionIntegrationWrapper::local_rendered_aspect_ratio() {
  if (local_rendered_height() == 0) {
    return 0.0;
  }
  return static_cast<double>(local_rendered_width()) / local_rendered_height();
}

size_t PeerConnectionIntegrationWrapper::number_of_remote_streams() {
  if (!pc()) {
    return 0;
  }
  return pc()->remote_streams()->count();
}

StreamCollectionInterface* PeerConnectionIntegrationWrapper::remote_streams()
    const {
  if (!pc()) {
    ADD_FAILURE();
    return nullptr;
  }
  return pc()->remote_streams().get();
}

StreamCollectionInterface* PeerConnectionIntegrationWrapper::local_streams() {
  if (!pc()) {
    ADD_FAILURE();
    return nullptr;
  }
  return pc()->local_streams().get();
}

PeerConnectionInterface::SignalingState
PeerConnectionIntegrationWrapper::signaling_state() {
  return pc()->signaling_state();
}

PeerConnectionInterface::IceConnectionState
PeerConnectionIntegrationWrapper::ice_connection_state() {
  return pc()->ice_connection_state();
}

PeerConnectionInterface::IceConnectionState
PeerConnectionIntegrationWrapper::standardized_ice_connection_state() {
  return pc()->standardized_ice_connection_state();
}

PeerConnectionInterface::IceGatheringState
PeerConnectionIntegrationWrapper::ice_gathering_state() {
  return pc()->ice_gathering_state();
}

void PeerConnectionIntegrationWrapper::ResetRtpReceiverObservers() {
  rtp_receiver_observers_.clear();
  for (const scoped_refptr<RtpReceiverInterface>& receiver :
       pc()->GetReceivers()) {
    std::unique_ptr<MockRtpReceiverObserver> observer(
        new MockRtpReceiverObserver(receiver->media_type()));
    receiver->SetObserver(observer.get());
    rtp_receiver_observers_.push_back(std::move(observer));
  }
}

void PeerConnectionIntegrationWrapper::ResetRtpSenderObservers() {
  rtp_sender_observers_.clear();
  for (const scoped_refptr<RtpSenderInterface>& sender : pc()->GetSenders()) {
    std::unique_ptr<MockRtpSenderObserver> observer(
        new MockRtpSenderObserver(sender->media_type()));
    sender->SetObserver(observer.get());
    rtp_sender_observers_.push_back(std::move(observer));
  }
}

Candidate PeerConnectionIntegrationWrapper::last_candidate_gathered() const {
  if (last_gathered_ice_candidate_) {
    return last_gathered_ice_candidate_->candidate();
  }
  return Candidate();
}

void PeerConnectionIntegrationWrapper::SetMdnsResponder(
    std::unique_ptr<FakeMdnsResponder> mdns_responder) {
  RTC_DCHECK(mdns_responder != nullptr);
  mdns_responder_ = mdns_responder.get();
  network_manager()->set_mdns_responder(std::move(mdns_responder));
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionIntegrationWrapper::CreateOfferAndWait() {
  auto observer = make_ref_counted<MockCreateSessionDescriptionObserver>();
  pc()->CreateOffer(observer.get(), offer_answer_options_);
  EXPECT_TRUE(test_->GetWaiter().Until([&] { return observer->called(); }));
  if (!observer->result()) {
    return nullptr;
  }
  auto description = observer->MoveDescription();
  if (generated_sdp_munger_) {
    generated_sdp_munger_(description);
  }
  return description;
}

bool PeerConnectionIntegrationWrapper::Rollback() {
  return SetRemoteDescription(CreateRollbackSessionDescription());
}

void PeerConnectionIntegrationWrapper::StartWatchingDelayStats() {
  // Get the baseline numbers for audio_packets and audio_delay.
  auto received_stats = NewGetStats();
  ASSERT_THAT(received_stats, NotNull());
  auto inbound_stats =
      received_stats->GetStatsOfType<RTCInboundRtpStreamStats>();
  ASSERT_FALSE(inbound_stats.empty());
  auto rtp_stats = inbound_stats[0];
  ASSERT_TRUE(rtp_stats->relative_packet_arrival_delay.has_value());
  ASSERT_TRUE(rtp_stats->packets_received.has_value());
  rtp_stats_id_ = rtp_stats->id();
  audio_packets_stat_ = *rtp_stats->packets_received;
  audio_delay_stat_ = *rtp_stats->relative_packet_arrival_delay;
  audio_samples_stat_ = *rtp_stats->total_samples_received;
  audio_concealed_stat_ = *rtp_stats->concealed_samples;
}

void PeerConnectionIntegrationWrapper::UpdateDelayStats(std::string tag,
                                                        int desc_size) {
  auto report = NewGetStats();
  auto rtp_stats = report->GetAs<RTCInboundRtpStreamStats>(rtp_stats_id_);
  ASSERT_TRUE(rtp_stats);
  auto delta_packets = *rtp_stats->packets_received - audio_packets_stat_;
  auto delta_rpad =
      *rtp_stats->relative_packet_arrival_delay - audio_delay_stat_;
  auto recent_delay = delta_packets > 0 ? delta_rpad / delta_packets : -1;
  // The purpose of these checks is to sound the alarm early if we introduce
  // serious regressions. The numbers are not acceptable for production, but
  // occur on slow bots.
  //
  // An average relative packet arrival delay over the renegotiation of
  // > 100 ms indicates that something is dramatically wrong, and will impact
  // quality for sure.
  // Worst bots:
  // linux_x86_dbg at 0.206
#if !defined(NDEBUG)
  EXPECT_GT(0.25, recent_delay) << tag << " size " << desc_size;
#else
  EXPECT_GT(0.1, recent_delay) << tag << " size " << desc_size;
#endif
  auto delta_samples = *rtp_stats->total_samples_received - audio_samples_stat_;
  auto delta_concealed = *rtp_stats->concealed_samples - audio_concealed_stat_;
  // These limits should be adjusted down as we improve:
  //
  // Concealing more than 4000 samples during a renegotiation is unacceptable.
  // But some bots are slow.

  // Worst bots:
  // linux_more_configs bot at conceal count 5184
  // android_arm_rel at conceal count 9241
  // linux_x86_dbg at 15174
#if !defined(NDEBUG)
  EXPECT_GT(18000U, delta_concealed) << "Concealed " << delta_concealed
                                     << " of " << delta_samples << " samples";
#else
  EXPECT_GT(15000U, delta_concealed) << "Concealed " << delta_concealed
                                     << " of " << delta_samples << " samples";
#endif
  // Concealing more than 20% of samples during a renegotiation is
  // unacceptable.
  // Worst bots:
  // Nondebug: Linux32 Release at conceal rate 0.606597 (CI run)
  // Debug: linux_x86_dbg bot at conceal rate 0.854
  //        internal bot at conceal rate 0.967 (b/294020344)
  // TODO(https://crbug.com/webrtc/15393): Improve audio quality during
  // renegotiation so that we can reduce these thresholds, 99% is not even
  // close to the 20% deemed unacceptable above or the 0% that would be ideal.
  // Require at least 2000 samples (roughly 2x 20ms packets).
  if (delta_samples >= 2000) {
    audio_delay_stats_percentage_checked_ = true;
#if !defined(NDEBUG)
    EXPECT_LT(1.0 * delta_concealed / delta_samples, 0.99)
        << "Concealed " << delta_concealed << " of " << delta_samples
        << " samples";
#else
    EXPECT_LT(1.0 * delta_concealed / delta_samples, 0.7)
        << "Concealed " << delta_concealed << " of " << delta_samples
        << " samples";
#endif
  }
  // Increment trailing counters
  audio_packets_stat_ = *rtp_stats->packets_received;
  audio_delay_stat_ = *rtp_stats->relative_packet_arrival_delay;
  audio_samples_stat_ = *rtp_stats->total_samples_received;
  audio_concealed_stat_ = *rtp_stats->concealed_samples;
}

bool PeerConnectionIntegrationWrapper::SetRemoteDescription(
    std::unique_ptr<SessionDescriptionInterface> desc) {
  auto observer = make_ref_counted<FakeSetRemoteDescriptionObserver>();
  std::string sdp;
  EXPECT_TRUE(desc->ToString(&sdp));
  RTC_LOG(LS_INFO) << debug_name_
                   << ": SetRemoteDescription SDP: type=" << desc->GetType()
                   << " contents=\n"
                   << sdp;
  pc()->SetRemoteDescription(std::move(desc), observer);
  RemoveUnusedVideoRenderers();
  EXPECT_THAT(test_->GetWaiter().Until([&] { return observer->called(); },
                                       ::testing::IsTrue()),
              IsRtcOk());
  auto err = observer->error();
  if (!err.ok()) {
    RTC_LOG(LS_WARNING) << debug_name_ << " SetRemoteDescription: " << err;
  }
  return observer->error().ok();
}

void PeerConnectionIntegrationWrapper::NegotiateCorruptionDetectionHeader() {
  for (const auto& transceiver : pc()->GetTransceivers()) {
    if (transceiver->media_type() != webrtc::MediaType::VIDEO) {
      continue;
    }
    auto extensions = transceiver->GetHeaderExtensionsToNegotiate();
    for (auto& extension : extensions) {
      if (extension.uri == RtpExtension::kCorruptionDetectionUri) {
        extension.direction = RtpTransceiverDirection::kSendRecv;
      }
    }
    transceiver->SetHeaderExtensionsToNegotiate(extensions);
  }
}

uint32_t PeerConnectionIntegrationWrapper::GetCorruptionScoreCount() {
  scoped_refptr<const RTCStatsReport> report = NewGetStats();
  auto inbound_stream_stats =
      report->GetStatsOfType<RTCInboundRtpStreamStats>();
  for (const auto& stat : inbound_stream_stats) {
    if (*stat->kind == "video") {
      return stat->corruption_measurements.value_or(0);
    }
  }
  return 0;
}

uint32_t PeerConnectionIntegrationWrapper::GetReceivedFrameCount() {
  scoped_refptr<const RTCStatsReport> report = NewGetStats();
  auto inbound_stream_stats =
      report->GetStatsOfType<RTCInboundRtpStreamStats>();
  for (const auto& stat : inbound_stream_stats) {
    if (*stat->kind == "video") {
      return stat->frames_received.value_or(0);
    }
  }
  return 0;
}

std::optional<int> PeerConnectionIntegrationWrapper::tls_version() {
  return dtls_transport_information().tls_version();
}

std::optional<DtlsTransportTlsRole>
PeerConnectionIntegrationWrapper::dtls_transport_role() {
  return dtls_transport_information().role();
}

DtlsTransportInformation
PeerConnectionIntegrationWrapper::dtls_transport_information() {
  return network_thread_->BlockingCall([&] {
    return pc()->GetSctpTransport()->dtls_transport()->Information();
  });
}

bool PeerConnectionIntegrationWrapper::SetLocalDescriptionAndSendSdpMessage(
    std::unique_ptr<SessionDescriptionInterface> desc) {
  auto observer = make_ref_counted<MockSetSessionDescriptionObserver>();
  RTC_LOG(LS_INFO) << debug_name_ << ": SetLocalDescriptionAndSendSdpMessage";
  SdpType type = desc->GetType();
  std::string sdp;
  EXPECT_TRUE(desc->ToString(&sdp));
  RTC_LOG(LS_INFO) << debug_name_ << ": local SDP type=" << desc->GetType()
                   << " contents=\n"
                   << sdp;
  pc()->SetLocalDescription(observer.get(), desc.release());
  // Note - many tests depend on the SDP message being sent before
  // SetLocalDescription returns.
  SendSdpMessage(type, sdp);
  EXPECT_THAT(test_->GetWaiter().Until([&] { return observer->called(); },
                                       ::testing::IsTrue()),
              IsRtcOk());
  return observer->result();
}

bool PeerConnectionIntegrationWrapper::Init(
    const PeerConnectionFactory::Options* options,
    const PeerConnectionInterface::RTCConfiguration* config,
    PeerConnectionDependencies dependencies,
    SocketServer* socket_server,
    Thread* network_thread,
    Thread* worker_thread,
    std::unique_ptr<FakeRtcEventLogFactory> event_log_factory,
    bool reset_encoder_factory,
    bool reset_decoder_factory,
    bool create_media_engine) {
  // There's an error in this test code if Init ends up being called twice.
  RTC_DCHECK(!peer_connection_);
  RTC_DCHECK(!peer_connection_factory_);

  auto network_manager = std::make_unique<FakeNetworkManager>(network_thread);
  fake_network_manager_ = network_manager.get();
  fake_network_manager_->AddInterface(kDefaultLocalAddress);

  network_thread_ = network_thread;

  fake_audio_capture_module_ =
      FakeAudioCaptureModule::Create(test_->CreateThread("AudioCaptureThread"));

  if (!fake_audio_capture_module_) {
    return false;
  }
  Thread* const signaling_thread = Thread::Current();

  PeerConnectionFactoryDependencies pc_factory_dependencies;
  pc_factory_dependencies.network_thread = network_thread;
  pc_factory_dependencies.worker_thread = worker_thread;
  pc_factory_dependencies.signaling_thread = signaling_thread;
  pc_factory_dependencies.socket_factory = socket_server;
  pc_factory_dependencies.network_manager = std::move(network_manager);
  pc_factory_dependencies.env = env_;
  pc_factory_dependencies.decode_metronome =
      std::make_unique<TaskQueueMetronome>(TimeDelta::Millis(8));

  pc_factory_dependencies.adm = fake_audio_capture_module_;
  if (create_media_engine) {
    // Standard creation method for APM may return a null pointer when
    // AudioProcessing is disabled with a build flag. Bypass that flag by
    // explicitly injecting the factory.
    pc_factory_dependencies.audio_processing_builder =
        std::make_unique<BuiltinAudioProcessingBuilder>();
    EnableMediaWithDefaults(pc_factory_dependencies);
  }

  if (reset_encoder_factory) {
    pc_factory_dependencies.video_encoder_factory.reset();
  }
  if (reset_decoder_factory) {
    pc_factory_dependencies.video_decoder_factory.reset();
  }

  if (event_log_factory) {
    event_log_factory_ = event_log_factory.get();
    pc_factory_dependencies.event_log_factory = std::move(event_log_factory);
  } else {
    pc_factory_dependencies.event_log_factory =
        std::make_unique<RtcEventLogFactory>();
  }
  peer_connection_factory_ =
      CreateModularPeerConnectionFactory(std::move(pc_factory_dependencies));

  if (!peer_connection_factory_) {
    fake_network_manager_ = nullptr;
    return false;
  }
  if (options) {
    peer_connection_factory_->SetOptions(*options);
  }
  if (config) {
    sdp_semantics_ = config->sdp_semantics;
  }

  peer_connection_ = CreatePeerConnection(config, std::move(dependencies));
  return peer_connection_.get() != nullptr;
}

scoped_refptr<PeerConnectionInterface>
PeerConnectionIntegrationWrapper::CreatePeerConnection(
    const PeerConnectionInterface::RTCConfiguration* config,
    PeerConnectionDependencies dependencies) {
  PeerConnectionInterface::RTCConfiguration modified_config;
  modified_config.sdp_semantics = sdp_semantics_;
  // If `config` is null, this will result in a default configuration being
  // used.
  if (config) {
    modified_config = *config;
  }
  // Disable resolution adaptation; we don't want it interfering with the
  // test results.
  // TODO(deadbeef): Do something more robust. Since we're testing for aspect
  // ratios and not specific resolutions, is this even necessary?
  modified_config.set_cpu_adaptation(false);

  dependencies.observer = this;
  auto peer_connection_or_error =
      peer_connection_factory_->CreatePeerConnectionOrError(
          modified_config, std::move(dependencies));
  return peer_connection_or_error.ok() ? peer_connection_or_error.MoveValue()
                                       : nullptr;
}

scoped_refptr<VideoTrackInterface>
PeerConnectionIntegrationWrapper::CreateLocalVideoTrackInternal(
    FakePeriodicVideoSource::Config config) {
  // Set max frame rate to 10fps to reduce the risk of test flakiness.
  // TODO(deadbeef): Do something more robust.
  config.frame_interval = TimeDelta::Millis(100);

  video_track_sources_.emplace_back(
      make_ref_counted<FakePeriodicVideoTrackSource>(config,
                                                     false /* remote */));
  scoped_refptr<VideoTrackInterface> track =
      peer_connection_factory_->CreateVideoTrack(video_track_sources_.back(),
                                                 CreateRandomUuid());
  if (!local_video_renderer_) {
    local_video_renderer_.reset(new FakeVideoTrackRenderer(track.get()));
  }
  return track;
}

void PeerConnectionIntegrationWrapper::HandleIncomingOffer(
    const std::string& msg) {
  RTC_LOG(LS_INFO) << debug_name_ << ": HandleIncomingOffer";
  std::unique_ptr<SessionDescriptionInterface> desc =
      CreateSessionDescription(SdpType::kOffer, msg);
  if (received_sdp_munger_) {
    received_sdp_munger_(desc);
  }

  EXPECT_TRUE(SetRemoteDescription(std::move(desc)));
  // Setting a remote description may have changed the number of receivers,
  // so reset the receiver observers.
  ResetRtpReceiverObservers();
  if (remote_offer_handler_) {
    remote_offer_handler_();
  }
  std::unique_ptr<SessionDescriptionInterface> answer = CreateAnswer();
  ASSERT_NE(nullptr, answer);
  EXPECT_TRUE(SetLocalDescriptionAndSendSdpMessage(std::move(answer)));
}

void PeerConnectionIntegrationWrapper::HandleIncomingAnswer(
    SdpType type,
    const std::string& msg) {
  RTC_LOG(LS_INFO) << debug_name_ << ": HandleIncomingAnswer of type " << type;
  std::unique_ptr<SessionDescriptionInterface> desc =
      CreateSessionDescription(type, msg);
  if (received_sdp_munger_) {
    received_sdp_munger_(desc);
    if (!desc) {
      // Answer was "taken" by munger...so that it can be applied later ?
      RTC_LOG(LS_INFO) << debug_name_ << ": answer NOT applied";
      return;
    }
  }
  EXPECT_TRUE(SetRemoteDescription(std::move(desc)));
  // Set the RtpReceiverObserver after receivers are created.
  ResetRtpReceiverObservers();
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionIntegrationWrapper::CreateAnswer() {
  auto observer = make_ref_counted<MockCreateSessionDescriptionObserver>();
  pc()->CreateAnswer(observer.get(), offer_answer_options_);
  EXPECT_THAT(test_->GetWaiter().Until([&] { return observer->called(); },
                                       ::testing::IsTrue()),
              IsRtcOk());
  if (!observer->result()) {
    return nullptr;
  }
  auto description = observer->MoveDescription();
  if (generated_sdp_munger_) {
    generated_sdp_munger_(description);
  }
  return description;
}

void PeerConnectionIntegrationWrapper::RemoveUnusedVideoRenderers() {
  if (sdp_semantics_ != SdpSemantics::kUnifiedPlan) {
    return;
  }
  auto transceivers = pc()->GetTransceivers();
  std::set<std::string> active_renderers;
  for (auto& transceiver : transceivers) {
    // Note - we don't check for direction here. This function is called
    // before direction is set, and in that case, we should not remove
    // the renderer.
    if (transceiver->receiver()->media_type() == webrtc::MediaType::VIDEO) {
      active_renderers.insert(transceiver->receiver()->track()->id());
    }
  }
  for (auto it = fake_video_renderers_.begin();
       it != fake_video_renderers_.end();) {
    // Remove fake video renderers belonging to any non-active transceivers.
    if (!active_renderers.count(it->first)) {
      it = fake_video_renderers_.erase(it);
    } else {
      it++;
    }
  }
}

void PeerConnectionIntegrationWrapper::SendSdpMessage(SdpType type,
                                                      const std::string& msg) {
  if (signaling_delay_ms_ == 0) {
    RelaySdpMessageIfReceiverExists(type, msg);
  } else {
    Thread::Current()->PostDelayedTask(
        SafeTask(
            task_safety_.flag(),
            [this, type, msg] { RelaySdpMessageIfReceiverExists(type, msg); }),
        TimeDelta::Millis(signaling_delay_ms_));
  }
}

void PeerConnectionIntegrationWrapper::RelaySdpMessageIfReceiverExists(
    SdpType type,
    const std::string& msg) {
  if (signaling_message_receiver_) {
    signaling_message_receiver_->ReceiveSdpMessage(type, msg);
  }
}

void PeerConnectionIntegrationWrapper::SendIceMessage(
    const std::string& sdp_mid,
    int sdp_mline_index,
    const std::string& msg) {
  if (signaling_delay_ms_ == 0) {
    RelayIceMessageIfReceiverExists(sdp_mid, sdp_mline_index, msg);
  } else {
    Thread::Current()->PostDelayedTask(
        SafeTask(task_safety_.flag(),
                 [this, sdp_mid, sdp_mline_index, msg] {
                   RelayIceMessageIfReceiverExists(sdp_mid, sdp_mline_index,
                                                   msg);
                 }),
        TimeDelta::Millis(signaling_delay_ms_));
  }
}

void PeerConnectionIntegrationWrapper::RelayIceMessageIfReceiverExists(
    const std::string& sdp_mid,
    int sdp_mline_index,
    const std::string& msg) {
  if (signaling_message_receiver_) {
    signaling_message_receiver_->ReceiveIceMessage(sdp_mid, sdp_mline_index,
                                                   msg);
  }
}

void PeerConnectionIntegrationWrapper::ReceiveSdpMessage(
    SdpType type,
    const std::string& msg) {
  if (type == SdpType::kOffer) {
    HandleIncomingOffer(msg);
  } else {
    HandleIncomingAnswer(type, msg);
  }
}

void PeerConnectionIntegrationWrapper::ReceiveIceMessage(
    const std::string& sdp_mid,
    int sdp_mline_index,
    const std::string& msg) {
  RTC_LOG(LS_INFO) << debug_name_ << ": ReceiveIceMessage";
  std::optional<RTCError> result;
  pc()->AddIceCandidate(absl::WrapUnique(CreateIceCandidate(
                            sdp_mid, sdp_mline_index, msg, nullptr)),
                        [&result](RTCError r) { result = r; });
  EXPECT_THAT(test_->GetWaiter().Until([&] { return result.has_value(); },
                                       ::testing::IsTrue()),
              IsRtcOk());
  EXPECT_TRUE(result.value().ok());
}

void PeerConnectionIntegrationWrapper::OnSignalingChange(
    PeerConnectionInterface::SignalingState new_state) {
  EXPECT_EQ(pc()->signaling_state(), new_state);
  peer_connection_signaling_state_history_.push_back(new_state);
}

void PeerConnectionIntegrationWrapper::OnAddTrack(
    scoped_refptr<RtpReceiverInterface> receiver,
    const std::vector<scoped_refptr<MediaStreamInterface>>& streams) {
  if (receiver->media_type() == webrtc::MediaType::VIDEO) {
    scoped_refptr<VideoTrackInterface> video_track(
        static_cast<VideoTrackInterface*>(receiver->track().get()));
    ASSERT_TRUE(fake_video_renderers_.find(video_track->id()) ==
                fake_video_renderers_.end());
    fake_video_renderers_[video_track->id()] =
        std::make_unique<FakeVideoTrackRenderer>(video_track.get());
  }
}

void PeerConnectionIntegrationWrapper::OnRemoveTrack(
    scoped_refptr<RtpReceiverInterface> receiver) {
  if (receiver->media_type() == webrtc::MediaType::VIDEO) {
    auto it = fake_video_renderers_.find(receiver->track()->id());
    if (it != fake_video_renderers_.end()) {
      fake_video_renderers_.erase(it);
    } else {
      RTC_LOG(LS_ERROR) << "OnRemoveTrack called for non-active renderer";
    }
  }
}

void PeerConnectionIntegrationWrapper::OnRenegotiationNeeded() {}

void PeerConnectionIntegrationWrapper::OnIceConnectionChange(
    PeerConnectionInterface::IceConnectionState new_state) {
  EXPECT_EQ(pc()->ice_connection_state(), new_state);
  ice_connection_state_history_.push_back(new_state);
}

void PeerConnectionIntegrationWrapper::OnStandardizedIceConnectionChange(
    PeerConnectionInterface::IceConnectionState new_state) {
  standardized_ice_connection_state_history_.push_back(new_state);
}

void PeerConnectionIntegrationWrapper::OnConnectionChange(
    PeerConnectionInterface::PeerConnectionState new_state) {
  peer_connection_state_history_.push_back(new_state);
  if (connection_change_callback_) {
    connection_change_callback_(new_state);
  }
}

void PeerConnectionIntegrationWrapper::OnIceGatheringChange(
    PeerConnectionInterface::IceGatheringState new_state) {
  EXPECT_EQ(pc()->ice_gathering_state(), new_state);
  ice_gathering_state_history_.push_back(new_state);
}

void PeerConnectionIntegrationWrapper::OnIceCandidate(
    const IceCandidate* candidate) {
  RTC_LOG(LS_INFO) << debug_name_ << ": OnIceCandidate";

  if (remote_async_dns_resolver_) {
    const auto& local_candidate = candidate->candidate();
    if (local_candidate.address().IsUnresolvedIP()) {
      RTC_DCHECK(local_candidate.is_local());
      const auto resolved_ip = mdns_responder_->GetMappedAddressForName(
          local_candidate.address().hostname());
      RTC_DCHECK(!resolved_ip.IsNil());
      remote_async_dns_resolved_addr_ = local_candidate.address();
      remote_async_dns_resolved_addr_.SetResolvedIP(resolved_ip);
      EXPECT_CALL(*remote_async_dns_resolver_, Start(_, _))
          .WillOnce([](const SocketAddress& addr,
                       absl::AnyInvocable<void()> callback) { callback(); });
      EXPECT_CALL(*remote_async_dns_resolver_, result())
          .WillOnce(ReturnRef(remote_async_dns_resolver_result_));
      EXPECT_CALL(remote_async_dns_resolver_result_, GetResolvedAddress(_, _))
          .WillOnce(DoAll(SetArgPointee<1>(remote_async_dns_resolved_addr_),
                          Return(true)));
    }
  }

  // Check if we expected to have a candidate.
  EXPECT_GT(candidates_expected_, 1);
  candidates_expected_--;
  std::string ice_sdp = candidate->ToString();
  if (signaling_message_receiver_ == nullptr || !signal_ice_candidates_) {
    // Remote party may be deleted.
    return;
  }
  SendIceMessage(candidate->sdp_mid(), candidate->sdp_mline_index(), ice_sdp);
  last_gathered_ice_candidate_ =
      CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(),
                         candidate->candidate());
}

void PeerConnectionIntegrationWrapper::OnIceCandidateError(
    const std::string& address,
    int port,
    const std::string& url,
    int error_code,
    const std::string& error_text) {
  error_event_ =
      IceCandidateErrorEvent(address, port, url, error_code, error_text);
}

void PeerConnectionIntegrationWrapper::OnDataChannel(
    scoped_refptr<DataChannelInterface> data_channel) {
  RTC_LOG(LS_INFO) << debug_name_ << ": OnDataChannel";
  data_channels_.push_back(data_channel);
  data_observers_.push_back(
      std::make_unique<MockDataChannelObserver>(data_channel.get()));
}

bool PeerConnectionIntegrationWrapper::IdExists(
    const RtpHeaderExtensions& extensions,
    int id) {
  for (const auto& extension : extensions) {
    if (extension.id == id) {
      return true;
    }
  }
  return false;
}

namespace internal {

// Utility class for tests that run multiple operations that cause excessive
// logging at the INFO level or below. Use to raise the logging level to e.g.
// LS_WARNING or above. Once an instance of ScopedSetLoggingLevel goes out of
// scope, the logging level is restored to what it was previously set to.
class PeerConnectionIntegrationTestBase::ScopedSetLoggingLevel {
 public:
  explicit ScopedSetLoggingLevel(LoggingSeverity new_severity) {
    LogMessage::LogToDebug(new_severity);
  }
  ~ScopedSetLoggingLevel() { LogMessage::LogToDebug(previous_severity_); }

 private:
  const LoggingSeverity previous_severity_ = LogMessage::GetLogToDebug();
};

PeerConnectionIntegrationTestBase::PeerConnectionIntegrationTestBase(
    Environment env,
    SdpSemantics sdp_semantics)
    : sdp_semantics_(sdp_semantics),
      env_(std::move(env)),
      ss_(new VirtualSocketServer()),
      fss_(new FirewallSocketServer(ss_.get(), nullptr, false)),
      network_thread_(new Thread(fss_.get())),
      worker_thread_(Thread::Create()) {
  network_thread_->SetName("PCNetworkThread", this);
  worker_thread_->SetName("PCWorkerThread", this);
  RTC_CHECK(network_thread_->Start());
  RTC_CHECK(worker_thread_->Start());
  metrics::Reset();
}

PeerConnectionIntegrationTestBase::PeerConnectionIntegrationTestBase(
    Environment env,
    SdpSemantics sdp_semantics,
    TimeController* time_controller)
    : sdp_semantics_(sdp_semantics), env_(std::move(env)) {
  ss_ = std::make_unique<VirtualSocketServer>();
  fss_ = std::make_unique<FirewallSocketServer>(ss_.get(), nullptr, false);
  network_thread_ = time_controller->CreateThreadWithSocketServer(
      "PCNetworkThread", fss_.get());
  worker_thread_ = time_controller->CreateThread("PCWorkerThread");
  network_thread_->SetName("PCNetworkThread", this);
  worker_thread_->SetName("PCWorkerThread", this);
  metrics::Reset();
}

PeerConnectionIntegrationTestBase::~PeerConnectionIntegrationTestBase() {
  // The PeerConnections should be deleted before the TurnCustomizers.
  // A TurnPort is created with a raw pointer to a TurnCustomizer. The
  // TurnPort has the same lifetime as the PeerConnection, so it's expected
  // that the TurnCustomizer outlives the life of the PeerConnection or else
  // when Send() is called it will hit a seg fault.
  DestroyPeerConnections();
}

bool PeerConnectionIntegrationTestBase::DtlsConnected() {
  // TODO(deadbeef): kIceConnectionConnected currently means both ICE and DTLS
  // are connected. This is an important distinction. Once we have separate
  // ICE and DTLS state, this check needs to use the DTLS state.
  return (callee()->ice_connection_state() ==
              PeerConnectionInterface::kIceConnectionConnected ||
          callee()->ice_connection_state() ==
              PeerConnectionInterface::kIceConnectionCompleted) &&
         (caller()->ice_connection_state() ==
              PeerConnectionInterface::kIceConnectionConnected ||
          caller()->ice_connection_state() ==
              PeerConnectionInterface::kIceConnectionCompleted);
}

void PeerConnectionIntegrationTestBase::SetFieldTrials(
    absl::string_view field_trials) {
  RTC_CHECK(caller_ == nullptr);
  RTC_CHECK(callee_ == nullptr);
  field_trials_ = std::string(field_trials);
}

void PeerConnectionIntegrationTestBase::SetFieldTrials(
    absl::string_view debug_name,
    absl::string_view field_trials) {
  RTC_CHECK(caller_ == nullptr);
  RTC_CHECK(callee_ == nullptr);
  field_trials_overrides_[std::string(debug_name)] = field_trials;
}

std::unique_ptr<PeerConnectionIntegrationWrapper>
PeerConnectionIntegrationTestBase::CreatePeerConnectionWrapper(
    const std::string& debug_name,
    const PeerConnectionFactory::Options* options,
    const RTCConfiguration* config,
    PeerConnectionDependencies dependencies,
    std::unique_ptr<FakeRtcEventLogFactory> event_log_factory,
    bool reset_encoder_factory,
    bool reset_decoder_factory,
    bool create_media_engine) {
  RTCConfiguration modified_config;
  if (config) {
    modified_config = *config;
  }
  modified_config.sdp_semantics = sdp_semantics_;
  if (!dependencies.cert_generator) {
    dependencies.cert_generator =
        std::make_unique<FakeRTCCertificateGenerator>();
  }
  std::string field_trials = field_trials_;
  EnvironmentFactory env = EnvironmentFactory(env_);

  auto it = field_trials_overrides_.find(debug_name);
  if (it != field_trials_overrides_.end()) {
    field_trials = it->second;
    dependencies.trials = CreateTestFieldTrialsPtr(it->second);
  }
  env.Set(CreateTestFieldTrialsPtr(field_trials));

  std::unique_ptr<PeerConnectionIntegrationWrapper> client =
      CreatePeerConnectionWrapperInternal(debug_name, env.Create());

  if (!client->Init(options, &modified_config, std::move(dependencies),
                    fss_.get(), network_thread_.get(), worker_thread_.get(),
                    std::move(event_log_factory), reset_encoder_factory,
                    reset_decoder_factory, create_media_engine)) {
    return nullptr;
  }
  return client;
}

std::unique_ptr<PeerConnectionIntegrationWrapper>
PeerConnectionIntegrationTestBase::
    CreatePeerConnectionWrapperWithFakeRtcEventLog(
        const std::string& debug_name,
        const PeerConnectionFactory::Options* options,
        const RTCConfiguration* config,
        PeerConnectionDependencies dependencies) {
  return CreatePeerConnectionWrapper(debug_name, options, config,
                                     std::move(dependencies),
                                     std::make_unique<FakeRtcEventLogFactory>(),
                                     /*reset_encoder_factory=*/false,
                                     /*reset_decoder_factory=*/false);
}

bool PeerConnectionIntegrationTestBase::
    CreatePeerConnectionWrappersWithSdpSemantics(
        SdpSemantics caller_semantics,
        SdpSemantics callee_semantics) {
  // Can't specify the sdp_semantics in the passed-in configuration since it
  // will be overwritten by CreatePeerConnectionWrapper with whatever is
  // stored in sdp_semantics_. So get around this by modifying the instance
  // variable before calling CreatePeerConnectionWrapper for the caller and
  // callee PeerConnections.
  SdpSemantics original_semantics = sdp_semantics_;
  sdp_semantics_ = caller_semantics;
  caller_ =
      CreatePeerConnectionWrapper(kCallerName, nullptr, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/false,
                                  /*reset_decoder_factory=*/false);
  sdp_semantics_ = callee_semantics;
  callee_ =
      CreatePeerConnectionWrapper(kCalleeName, nullptr, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/false,
                                  /*reset_decoder_factory=*/false);
  sdp_semantics_ = original_semantics;
  return caller_ && callee_;
}

bool PeerConnectionIntegrationTestBase::CreatePeerConnectionWrappersWithConfig(
    const PeerConnectionInterface::RTCConfiguration& caller_config,
    const PeerConnectionInterface::RTCConfiguration& callee_config,
    bool create_media_engine) {
  caller_ = CreatePeerConnectionWrapper(
      kCallerName, nullptr, &caller_config, PeerConnectionDependencies(nullptr),
      nullptr,
      /*reset_encoder_factory=*/false,
      /*reset_decoder_factory=*/false, create_media_engine);
  callee_ = CreatePeerConnectionWrapper(
      kCalleeName, nullptr, &callee_config, PeerConnectionDependencies(nullptr),
      nullptr,
      /*reset_encoder_factory=*/false,
      /*reset_decoder_factory=*/false, create_media_engine);
  return caller_ && callee_;
}

bool PeerConnectionIntegrationTestBase::
    CreatePeerConnectionWrappersWithConfigAndDeps(
        const PeerConnectionInterface::RTCConfiguration& caller_config,
        PeerConnectionDependencies caller_dependencies,
        const PeerConnectionInterface::RTCConfiguration& callee_config,
        PeerConnectionDependencies callee_dependencies) {
  caller_ = CreatePeerConnectionWrapper(kCallerName, nullptr, &caller_config,
                                        std::move(caller_dependencies), nullptr,
                                        /*reset_encoder_factory=*/false,
                                        /*reset_decoder_factory=*/false);
  callee_ = CreatePeerConnectionWrapper(kCalleeName, nullptr, &callee_config,
                                        std::move(callee_dependencies), nullptr,
                                        /*reset_encoder_factory=*/false,
                                        /*reset_decoder_factory=*/false);
  return caller_ && callee_;
}

bool PeerConnectionIntegrationTestBase::CreatePeerConnectionWrappersWithOptions(
    const PeerConnectionFactory::Options& caller_options,
    const PeerConnectionFactory::Options& callee_options) {
  caller_ =
      CreatePeerConnectionWrapper(kCallerName, &caller_options, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/false,
                                  /*reset_decoder_factory=*/false);
  callee_ =
      CreatePeerConnectionWrapper(kCalleeName, &callee_options, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/false,
                                  /*reset_decoder_factory=*/false);
  return caller_ && callee_;
}

bool PeerConnectionIntegrationTestBase::
    CreatePeerConnectionWrappersWithFakeRtcEventLog() {
  PeerConnectionInterface::RTCConfiguration default_config;
  caller_ = CreatePeerConnectionWrapperWithFakeRtcEventLog(
      kCallerName, nullptr, &default_config,
      PeerConnectionDependencies(nullptr));
  callee_ = CreatePeerConnectionWrapperWithFakeRtcEventLog(
      kCalleeName, nullptr, &default_config,
      PeerConnectionDependencies(nullptr));
  return caller_ && callee_;
}

std::unique_ptr<PeerConnectionIntegrationWrapper>
PeerConnectionIntegrationTestBase::
    CreatePeerConnectionWrapperWithAlternateKey() {
  std::unique_ptr<FakeRTCCertificateGenerator> cert_generator(
      new FakeRTCCertificateGenerator());
  cert_generator->use_alternate_key();

  PeerConnectionDependencies dependencies(nullptr);
  dependencies.cert_generator = std::move(cert_generator);
  return CreatePeerConnectionWrapper("New Peer", nullptr, nullptr,
                                     std::move(dependencies), nullptr,
                                     /*reset_encoder_factory=*/false,
                                     /*reset_decoder_factory=*/false);
}

bool PeerConnectionIntegrationTestBase::
    CreateOneDirectionalPeerConnectionWrappers(bool caller_to_callee) {
  caller_ =
      CreatePeerConnectionWrapper(kCallerName, nullptr, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/!caller_to_callee,
                                  /*reset_decoder_factory=*/caller_to_callee);
  callee_ =
      CreatePeerConnectionWrapper(kCalleeName, nullptr, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/caller_to_callee,
                                  /*reset_decoder_factory=*/!caller_to_callee);
  return caller_ && callee_;
}

bool PeerConnectionIntegrationTestBase::
    CreatePeerConnectionWrappersWithoutMediaEngine() {
  caller_ =
      CreatePeerConnectionWrapper(kCallerName, nullptr, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/false,
                                  /*reset_decoder_factory=*/false,
                                  /*create_media_engine=*/false);
  callee_ =
      CreatePeerConnectionWrapper(kCalleeName, nullptr, nullptr,
                                  PeerConnectionDependencies(nullptr), nullptr,
                                  /*reset_encoder_factory=*/false,
                                  /*reset_decoder_factory=*/false,
                                  /*create_media_engine=*/false);
  return caller_ && callee_;
}

TestTurnServer* PeerConnectionIntegrationTestBase::CreateTurnServer(
    SocketAddress internal_address,
    SocketAddress external_address,
    ProtocolType type,
    const std::string& common_name) {
  Thread* thread = network_thread();
  SocketFactory* socket_factory = fss_.get();
  std::unique_ptr<TestTurnServer> turn_server;
  SendTask(network_thread(), [&] {
    turn_server = std::make_unique<TestTurnServer>(
        CreateTestEnvironment(), thread, socket_factory, internal_address,
        external_address, type,
        /*ignore_bad_certs=*/true, common_name);
  });
  turn_servers_.push_back(std::move(turn_server));
  // Interactions with the turn server should be done on the network thread.
  return turn_servers_.back().get();
}

TestTurnCustomizer* PeerConnectionIntegrationTestBase::CreateTurnCustomizer() {
  std::unique_ptr<TestTurnCustomizer> turn_customizer;
  SendTask(network_thread(),
           [&] { turn_customizer = std::make_unique<TestTurnCustomizer>(); });
  turn_customizers_.push_back(std::move(turn_customizer));
  // Interactions with the turn customizer should be done on the network
  // thread.
  return turn_customizers_.back().get();
}

void PeerConnectionIntegrationTestBase::ExpectTurnCustomizerCountersIncremented(
    TestTurnCustomizer* turn_customizer) {
  SendTask(network_thread(), [turn_customizer] {
    EXPECT_GT(turn_customizer->allow_channel_data_cnt_, 0u);
    EXPECT_GT(turn_customizer->modify_cnt_, 0u);
  });
}

void PeerConnectionIntegrationTestBase::ConnectFakeSignaling() {
  caller_->set_signaling_message_receiver(callee_.get());
  callee_->set_signaling_message_receiver(caller_.get());
}

void PeerConnectionIntegrationTestBase::ConnectFakeSignalingForSdpOnly() {
  ConnectFakeSignaling();
  SetSignalIceCandidates(false);
}

void PeerConnectionIntegrationTestBase::SetSignalingDelayMs(int delay_ms) {
  caller_->set_signaling_delay_ms(delay_ms);
  callee_->set_signaling_delay_ms(delay_ms);
}

void PeerConnectionIntegrationTestBase::SetSignalIceCandidates(bool signal) {
  caller_->set_signal_ice_candidates(signal);
  callee_->set_signal_ice_candidates(signal);
}

void PeerConnectionIntegrationTestBase::SendRtpDataWithRetries(
    DataChannelInterface* dc,
    const std::string& data,
    int retries) {
  for (int i = 0; i < retries; ++i) {
    dc->Send(DataBuffer(data));
  }
}

void PeerConnectionIntegrationTestBase::DestroyTurnServers() {
  ExecuteTask(*network_thread(), [this] {
    turn_servers_.clear();
    turn_customizers_.clear();
  });
}

void PeerConnectionIntegrationTestBase::DestroyThreads() {
  worker_thread_.reset();
  network_thread_.reset();
}

void PeerConnectionIntegrationTestBase::OverrideLoggingLevelForTest(
    LoggingSeverity new_severity) {
  RTC_DCHECK(!overridden_logging_level_);
  overridden_logging_level_ =
      std::make_unique<ScopedSetLoggingLevel>(new_severity);
}

void PeerConnectionIntegrationTestBase::DestroyPeerConnections() {
  if (caller_) {
    caller_->set_signaling_message_receiver(nullptr);
    caller_->pc()->Close();
  }
  if (callee_) {
    callee_->set_signaling_message_receiver(nullptr);
    callee_->pc()->Close();
  }
  caller_.reset();
  callee_.reset();
}

PeerConnectionIntegrationWrapper*
PeerConnectionIntegrationTestBase::SetCallerPcWrapperAndReturnCurrent(
    std::unique_ptr<PeerConnectionIntegrationWrapper> wrapper) {
  PeerConnectionIntegrationWrapper* old = caller_.release();
  caller_ = std::move(wrapper);
  return old;
}

PeerConnectionIntegrationWrapper*
PeerConnectionIntegrationTestBase::SetCalleePcWrapperAndReturnCurrent(
    std::unique_ptr<PeerConnectionIntegrationWrapper> wrapper) {
  PeerConnectionIntegrationWrapper* old = callee_.release();
  callee_ = std::move(wrapper);
  return old;
}

bool PeerConnectionIntegrationTestBase::ExpectNewFrames(
    const MediaExpectations& media_expectations) {
  // Make sure there are no bogus tracks confusing the issue.
  caller()->RemoveUnusedVideoRenderers();
  callee()->RemoveUnusedVideoRenderers();
  // First initialize the expected frame counts based upon the current
  // frame count.
  int total_caller_audio_frames_expected = caller()->audio_frames_received();
  if (media_expectations.caller_audio_expectation_ ==
      MediaExpectations::kExpectSomeFrames) {
    total_caller_audio_frames_expected +=
        media_expectations.caller_audio_frames_expected_;
  }
  int total_caller_video_frames_expected =
      caller()->min_video_frames_received_per_track();
  if (media_expectations.caller_video_expectation_ ==
      MediaExpectations::kExpectSomeFrames) {
    total_caller_video_frames_expected +=
        media_expectations.caller_video_frames_expected_;
  }
  int total_callee_audio_frames_expected = callee()->audio_frames_received();
  if (media_expectations.callee_audio_expectation_ ==
      MediaExpectations::kExpectSomeFrames) {
    total_callee_audio_frames_expected +=
        media_expectations.callee_audio_frames_expected_;
  }
  int total_callee_video_frames_expected =
      callee()->min_video_frames_received_per_track();
  if (media_expectations.callee_video_expectation_ ==
      MediaExpectations::kExpectSomeFrames) {
    total_callee_video_frames_expected +=
        media_expectations.callee_video_frames_expected_;
  }

  // Wait for the expected frames.
  EXPECT_THAT(
      GetWaiter({.timeout = kMaxWaitForFrames})
          .Until(
              [&] {
                return caller()->audio_frames_received() >=
                           total_caller_audio_frames_expected &&
                       caller()->min_video_frames_received_per_track() >=
                           total_caller_video_frames_expected &&
                       callee()->audio_frames_received() >=
                           total_callee_audio_frames_expected &&
                       callee()->min_video_frames_received_per_track() >=
                           total_callee_video_frames_expected;
              },
              ::testing::IsTrue()),
      IsRtcOk());
  bool expectations_correct =
      caller()->audio_frames_received() >= total_caller_audio_frames_expected &&
      caller()->min_video_frames_received_per_track() >=
          total_caller_video_frames_expected &&
      callee()->audio_frames_received() >= total_callee_audio_frames_expected &&
      callee()->min_video_frames_received_per_track() >=
          total_callee_video_frames_expected;

  // After the combined wait, print out a more detailed message upon
  // failure.
  EXPECT_GE(caller()->audio_frames_received(),
            total_caller_audio_frames_expected);
  EXPECT_GE(caller()->min_video_frames_received_per_track(),
            total_caller_video_frames_expected);
  EXPECT_GE(callee()->audio_frames_received(),
            total_callee_audio_frames_expected);
  EXPECT_GE(callee()->min_video_frames_received_per_track(),
            total_callee_video_frames_expected);

  // We want to make sure nothing unexpected was received.
  if (media_expectations.caller_audio_expectation_ ==
      MediaExpectations::kExpectNoFrames) {
    EXPECT_EQ(caller()->audio_frames_received(),
              total_caller_audio_frames_expected);
    if (caller()->audio_frames_received() !=
        total_caller_audio_frames_expected) {
      expectations_correct = false;
    }
  }
  if (media_expectations.caller_video_expectation_ ==
      MediaExpectations::kExpectNoFrames) {
    EXPECT_EQ(caller()->min_video_frames_received_per_track(),
              total_caller_video_frames_expected);
    if (caller()->min_video_frames_received_per_track() !=
        total_caller_video_frames_expected) {
      expectations_correct = false;
    }
  }
  if (media_expectations.callee_audio_expectation_ ==
      MediaExpectations::kExpectNoFrames) {
    EXPECT_EQ(callee()->audio_frames_received(),
              total_callee_audio_frames_expected);
    if (callee()->audio_frames_received() !=
        total_callee_audio_frames_expected) {
      expectations_correct = false;
    }
  }
  if (media_expectations.callee_video_expectation_ ==
      MediaExpectations::kExpectNoFrames) {
    EXPECT_EQ(callee()->min_video_frames_received_per_track(),
              total_callee_video_frames_expected);
    if (callee()->min_video_frames_received_per_track() !=
        total_callee_video_frames_expected) {
      expectations_correct = false;
    }
  }
  return expectations_correct;
}

void PeerConnectionIntegrationTestBase::ClosePeerConnections() {
  if (caller())
    caller()->pc()->Close();
  if (callee())
    callee()->pc()->Close();
}

void PeerConnectionIntegrationTestBase::TestNegotiatedCipherSuite(
    const RTCConfiguration& caller_config,
    const RTCConfiguration& callee_config,
    int expected_cipher_suite) {
  ASSERT_TRUE(
      CreatePeerConnectionWrappersWithConfig(caller_config, callee_config));
  ConnectFakeSignaling();
  caller()->AddAudioVideoTracks();
  callee()->AddAudioVideoTracks();
  caller()->CreateAndSetAndSignalOffer();
  WaitUntilSettings settings;
  settings.polling_interval = TimeDelta::Millis(100);
  if (auto* tc = time_controller()) {
    settings.clock = tc;
  }
  ASSERT_THAT(GetWaiter(settings).Until([&] { return DtlsConnected(); },
                                        ::testing::IsTrue()),
              IsRtcOk());
  EXPECT_THAT(GetWaiter(settings).Until(
                  [&] {
                    auto report = caller()->NewGetStats(settings);
                    if (!report) {
                      return false;
                    }
                    auto transport_stats =
                        report->GetStatsOfType<RTCTransportStats>();
                    if (transport_stats.empty()) {
                      return false;
                    }
                    return *transport_stats[0]->srtp_cipher ==
                           SrtpCryptoSuiteToName(expected_cipher_suite);
                  },
                  ::testing::IsTrue()),
              IsRtcOk());
}

void PeerConnectionIntegrationTestBase::TestGcmNegotiationUsesCipherSuite(
    bool local_gcm_enabled,
    bool remote_gcm_enabled,
    bool aes_ctr_enabled,
    int expected_cipher_suite) {
  RTCConfiguration caller_config;
  CryptoOptions caller_crypto;
  caller_crypto.srtp.enable_gcm_crypto_suites = local_gcm_enabled;
  caller_crypto.srtp.enable_aes128_sha1_80_crypto_cipher = aes_ctr_enabled;
  caller_config.crypto_options = caller_crypto;
  RTCConfiguration callee_config;
  CryptoOptions callee_crypto;
  callee_crypto.srtp.enable_gcm_crypto_suites = remote_gcm_enabled;
  callee_crypto.srtp.enable_aes128_sha1_80_crypto_cipher = aes_ctr_enabled;
  callee_config.crypto_options = callee_crypto;
  TestNegotiatedCipherSuite(caller_config, callee_config,
                            expected_cipher_suite);
}

std::unique_ptr<PeerConnectionIntegrationWrapper>
PeerConnectionIntegrationTestBase::CreatePeerConnectionWrapperInternal(
    const std::string& debug_name,
    Environment env) {
  return std::unique_ptr<PeerConnectionIntegrationWrapper>(
      new PeerConnectionIntegrationWrapper(debug_name, env, this));
}

}  // namespace internal

PeerConnectionIntegrationBaseTest::PeerConnectionIntegrationBaseTest(
    SdpSemantics sdp_semantics)
    : internal::PeerConnectionIntegrationTestBase(CreateTestEnvironment(),
                                                  sdp_semantics) {}

PeerConnectionIntegrationBaseTest::~PeerConnectionIntegrationBaseTest() {
  DestroyPeerConnections();
  DestroyTurnServers();
}

void PeerConnectionIntegrationBaseTest::ExecuteTask(
    TaskQueueBase& task_queue,
    absl::AnyInvocable<void()> task) {
  task_queue.PostTask([this, task = std::move(task)]() mutable {
    task();
    run_loop_.task_queue()->PostTask(run_loop_.QuitClosure());
  });
  run_loop_.Run();
}

Waiter PeerConnectionIntegrationBaseTest::GetWaiter(
    WaitUntilSettings overrides) {
  return Waiter(overrides);
}

std::unique_ptr<Thread> PeerConnectionIntegrationBaseTest::CreateThread(
    absl::string_view name) {
  auto thread = Thread::Create();
  thread->Start();
  return thread;
}

PeerConnectionIntegrationTestWithSimulatedTime::
    PeerConnectionIntegrationTestWithSimulatedTime(SdpSemantics sdp_semantics)
    : PeerConnectionIntegrationTestWithSimulatedTime(
          sdp_semantics,
          std::make_unique<GlobalSimulatedTimeController>(
              Timestamp::Seconds(1000))) {}

PeerConnectionIntegrationTestWithSimulatedTime::
    ~PeerConnectionIntegrationTestWithSimulatedTime() {
  DestroyPeerConnections();
  DestroyTurnServers();
  time_controller_->AdvanceTime(TimeDelta::Zero());
  // Explicitly destroy threads before time_controller_ is destroyed.
  // Simulated threads hold a pointer to the time controller and will
  // attempt to unregister from it in their destructor. Since time_controller_
  // is owned by this derived class, it will be destroyed BEFORE the base
  // class destroys the threads, causing a crash if we don't do this here.
  DestroyThreads();
}

void PeerConnectionIntegrationTestWithSimulatedTime::ExecuteTask(
    TaskQueueBase& task_queue,
    absl::AnyInvocable<void()> task) {
  task_queue.PostTask(std::move(task));
  time_controller_->AdvanceTime(TimeDelta::Zero());
}

Waiter PeerConnectionIntegrationTestWithSimulatedTime::GetWaiter(
    WaitUntilSettings overrides) {
  overrides.clock = time_controller_.get();
  return Waiter(overrides);
}

std::unique_ptr<Thread>
PeerConnectionIntegrationTestWithSimulatedTime::CreateThread(
    absl::string_view name) {
  return time_controller_->CreateThread(std::string(name), nullptr);
}

PeerConnectionIntegrationTestWithSimulatedTime::
    PeerConnectionIntegrationTestWithSimulatedTime(
        SdpSemantics sdp_semantics,
        std::unique_ptr<GlobalSimulatedTimeController> time_controller)
    : internal::PeerConnectionIntegrationTestBase(
          [](TimeController* tc) {
            CreateTestEnvironmentOptions options;
            options.time = tc;
            return CreateTestEnvironment(std::move(options));
          }(time_controller.get()),
          sdp_semantics,
          time_controller.get()),
      time_controller_(std::move(time_controller)) {}

// Tests whether a parameter set contains duplicate payload types.
// Copied from sdp_offer_answer.cc
RTCError FindDuplicateCodecParameters(
    const RtpCodecParameters codec_parameters,
    flat_map<PayloadType, RtpCodecParameters>& payload_to_codec_parameters) {
  auto existing_codec_parameters =
      payload_to_codec_parameters.find(codec_parameters.payload_type);
  if (existing_codec_parameters != payload_to_codec_parameters.end() &&
      codec_parameters != existing_codec_parameters->second) {
    return LOG_ERROR(RTCError(RTCErrorType::INVALID_PARAMETER)
                     << "A BUNDLE group contains a codec collision for "
                     << "payload_type='" << codec_parameters.payload_type
                     << ". All codecs must share the same type, "
                     << "encoding name, clock rate and parameters.");
  }
  payload_to_codec_parameters.try_emplace(codec_parameters.payload_type,
                                          codec_parameters);
  return RTCError::OK();
}

// Tests whether a session description contains conflicting descriptions
// for a payload type.
// Copied from sdp_offer_answer.cc
RTCError ValidateBundledPayloadTypes(const SessionDescription& description) {
  // https://www.rfc-editor.org/rfc/rfc8843#name-payload-type-pt-value-reuse
  // ... all codecs associated with the payload type number MUST share an
  // identical codec configuration. This means that the codecs MUST share
  // the same media type, encoding name, clock rate, and any parameter
  // that can affect the codec configuration and packetization.
  std::vector<const ContentGroup*> bundle_groups =
      description.GetGroupsByName(GROUP_TYPE_BUNDLE);
  for (const ContentGroup* bundle_group : bundle_groups) {
    flat_map<PayloadType, RtpCodecParameters> payload_to_codec_parameters;
    for (const std::string& content_name : bundle_group->content_names()) {
      const ContentInfo* content_description =
          description.GetContentByName(content_name);
      if (content_description == nullptr) {
        return LOG_ERROR(RTCError(RTCErrorType::INVALID_PARAMETER)
                         << "A BUNDLE group contains a MID='" << content_name
                         << "' matching no m= section.");
      }
      const MediaContentDescription* media_description =
          content_description->media_description();
      RTC_DCHECK(media_description);
      if (content_description->rejected || !media_description->has_codecs()) {
        continue;
      }
      const MediaType type = media_description->type();
      if (type == MediaType::AUDIO || type == MediaType::VIDEO) {
        for (const Codec& c : media_description->codecs()) {
          RTCError error = FindDuplicateCodecParameters(
              c.ToCodecParameters(), payload_to_codec_parameters);
          if (!error.ok()) {
            return error;
          }
        }
      }
    }
  }
  return RTCError::OK();
}

}  // namespace webrtc
