blob: b4842c120e84cbde4478c75ac905ac547181b571 [file] [log] [blame]
/*
* 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 "pc/peer_connection_wrapper.h"
#include <stdint.h>
#include <optional>
#include <utility>
#include <vector>
#include "api/function_view.h"
#include "api/set_remote_description_observer_interface.h"
#include "pc/sdp_utils.h"
#include "pc/test/fake_video_track_source.h"
#include "rtc_base/checks.h"
#include "rtc_base/gunit.h"
#include "rtc_base/logging.h"
#include "test/gtest.h"
namespace webrtc {
using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
namespace {
const uint32_t kDefaultTimeout = 10000U;
}
PeerConnectionWrapper::PeerConnectionWrapper(
rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
rtc::scoped_refptr<PeerConnectionInterface> pc,
std::unique_ptr<MockPeerConnectionObserver> observer)
: pc_factory_(std::move(pc_factory)),
observer_(std::move(observer)),
pc_(std::move(pc)) {
RTC_DCHECK(pc_factory_);
RTC_DCHECK(pc_);
RTC_DCHECK(observer_);
observer_->SetPeerConnectionInterface(pc_.get());
}
PeerConnectionWrapper::~PeerConnectionWrapper() {
if (pc_)
pc_->Close();
}
PeerConnectionFactoryInterface* PeerConnectionWrapper::pc_factory() {
return pc_factory_.get();
}
PeerConnectionInterface* PeerConnectionWrapper::pc() {
return pc_.get();
}
MockPeerConnectionObserver* PeerConnectionWrapper::observer() {
return observer_.get();
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateOffer() {
return CreateOffer(RTCOfferAnswerOptions());
}
std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
std::string* error_out) {
return CreateSdp(
[this, options](CreateSessionDescriptionObserver* observer) {
pc()->CreateOffer(observer, options);
},
error_out);
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateOfferAndSetAsLocal() {
return CreateOfferAndSetAsLocal(RTCOfferAnswerOptions());
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateOfferAndSetAsLocal(
const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
auto offer = CreateOffer(options);
if (!offer) {
return nullptr;
}
EXPECT_TRUE(SetLocalDescription(CloneSessionDescription(offer.get())));
return offer;
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswer() {
return CreateAnswer(RTCOfferAnswerOptions());
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswer(
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
std::string* error_out) {
return CreateSdp(
[this, options](CreateSessionDescriptionObserver* observer) {
pc()->CreateAnswer(observer, options);
},
error_out);
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswerAndSetAsLocal() {
return CreateAnswerAndSetAsLocal(RTCOfferAnswerOptions());
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswerAndSetAsLocal(
const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
auto answer = CreateAnswer(options);
if (!answer) {
return nullptr;
}
EXPECT_TRUE(SetLocalDescription(CloneSessionDescription(answer.get())));
return answer;
}
std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateRollback() {
return CreateSessionDescription(SdpType::kRollback, "");
}
std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateSdp(
rtc::FunctionView<void(CreateSessionDescriptionObserver*)> fn,
std::string* error_out) {
auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
fn(observer.get());
EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
if (error_out && !observer->result()) {
*error_out = observer->error();
}
return observer->MoveDescription();
}
bool PeerConnectionWrapper::SetLocalDescription(
std::unique_ptr<SessionDescriptionInterface> desc,
std::string* error_out) {
return SetSdp(
[this, &desc](SetSessionDescriptionObserver* observer) {
pc()->SetLocalDescription(observer, desc.release());
},
error_out);
}
bool PeerConnectionWrapper::SetRemoteDescription(
std::unique_ptr<SessionDescriptionInterface> desc,
std::string* error_out) {
return SetSdp(
[this, &desc](SetSessionDescriptionObserver* observer) {
pc()->SetRemoteDescription(observer, desc.release());
},
error_out);
}
bool PeerConnectionWrapper::SetRemoteDescription(
std::unique_ptr<SessionDescriptionInterface> desc,
RTCError* error_out) {
auto observer = rtc::make_ref_counted<FakeSetRemoteDescriptionObserver>();
pc()->SetRemoteDescription(std::move(desc), observer);
EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
bool ok = observer->error().ok();
if (error_out)
*error_out = std::move(observer->error());
return ok;
}
bool PeerConnectionWrapper::SetSdp(
rtc::FunctionView<void(SetSessionDescriptionObserver*)> fn,
std::string* error_out) {
auto observer = rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
fn(observer.get());
EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
if (error_out && !observer->result()) {
*error_out = observer->error();
}
return observer->result();
}
bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
PeerConnectionWrapper* answerer) {
return ExchangeOfferAnswerWith(answerer, RTCOfferAnswerOptions(),
RTCOfferAnswerOptions());
}
bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
PeerConnectionWrapper* answerer,
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_options,
const PeerConnectionInterface::RTCOfferAnswerOptions& answer_options) {
RTC_DCHECK(answerer);
if (answerer == this) {
RTC_LOG(LS_ERROR) << "Cannot exchange offer/answer with ourself!";
return false;
}
auto offer = CreateOffer(offer_options);
EXPECT_TRUE(offer);
if (!offer) {
return false;
}
bool set_local_offer =
SetLocalDescription(CloneSessionDescription(offer.get()));
EXPECT_TRUE(set_local_offer);
if (!set_local_offer) {
return false;
}
bool set_remote_offer = answerer->SetRemoteDescription(std::move(offer));
EXPECT_TRUE(set_remote_offer);
if (!set_remote_offer) {
return false;
}
auto answer = answerer->CreateAnswer(answer_options);
EXPECT_TRUE(answer);
if (!answer) {
return false;
}
bool set_local_answer =
answerer->SetLocalDescription(CloneSessionDescription(answer.get()));
EXPECT_TRUE(set_local_answer);
if (!set_local_answer) {
return false;
}
bool set_remote_answer = SetRemoteDescription(std::move(answer));
EXPECT_TRUE(set_remote_answer);
return set_remote_answer;
}
rtc::scoped_refptr<RtpTransceiverInterface>
PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type) {
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
pc()->AddTransceiver(media_type);
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
return result.MoveValue();
}
rtc::scoped_refptr<RtpTransceiverInterface>
PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type,
const RtpTransceiverInit& init) {
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
pc()->AddTransceiver(media_type, init);
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
return result.MoveValue();
}
rtc::scoped_refptr<RtpTransceiverInterface>
PeerConnectionWrapper::AddTransceiver(
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
pc()->AddTransceiver(track);
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
return result.MoveValue();
}
rtc::scoped_refptr<RtpTransceiverInterface>
PeerConnectionWrapper::AddTransceiver(
rtc::scoped_refptr<MediaStreamTrackInterface> track,
const RtpTransceiverInit& init) {
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
pc()->AddTransceiver(track, init);
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
return result.MoveValue();
}
rtc::scoped_refptr<AudioTrackInterface> PeerConnectionWrapper::CreateAudioTrack(
const std::string& label) {
return pc_factory()->CreateAudioTrack(label, nullptr);
}
rtc::scoped_refptr<VideoTrackInterface> PeerConnectionWrapper::CreateVideoTrack(
const std::string& label) {
return pc_factory()->CreateVideoTrack(FakeVideoTrackSource::Create(), label);
}
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
rtc::scoped_refptr<MediaStreamTrackInterface> track,
const std::vector<std::string>& stream_ids) {
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
pc()->AddTrack(track, stream_ids);
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
return result.MoveValue();
}
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
rtc::scoped_refptr<MediaStreamTrackInterface> track,
const std::vector<std::string>& stream_ids,
const std::vector<RtpEncodingParameters>& init_send_encodings) {
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
pc()->AddTrack(track, stream_ids, init_send_encodings);
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
return result.MoveValue();
}
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
const std::string& track_label,
const std::vector<std::string>& stream_ids) {
return AddTrack(CreateAudioTrack(track_label), stream_ids);
}
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddVideoTrack(
const std::string& track_label,
const std::vector<std::string>& stream_ids) {
return AddTrack(CreateVideoTrack(track_label), stream_ids);
}
rtc::scoped_refptr<DataChannelInterface>
PeerConnectionWrapper::CreateDataChannel(
const std::string& label,
const std::optional<DataChannelInit>& config) {
const DataChannelInit* config_ptr = config.has_value() ? &(*config) : nullptr;
auto result = pc()->CreateDataChannelOrError(label, config_ptr);
if (!result.ok()) {
RTC_LOG(LS_ERROR) << "CreateDataChannel failed: "
<< ToString(result.error().type()) << " "
<< result.error().message();
return nullptr;
}
return result.MoveValue();
}
PeerConnectionInterface::SignalingState
PeerConnectionWrapper::signaling_state() {
return pc()->signaling_state();
}
bool PeerConnectionWrapper::IsIceGatheringDone() {
return observer()->ice_gathering_complete_;
}
bool PeerConnectionWrapper::IsIceConnected() {
return observer()->ice_connected_;
}
rtc::scoped_refptr<const RTCStatsReport> PeerConnectionWrapper::GetStats() {
auto callback = rtc::make_ref_counted<MockRTCStatsCollectorCallback>();
pc()->GetStats(callback.get());
EXPECT_TRUE_WAIT(callback->called(), kDefaultTimeout);
return callback->report();
}
} // namespace webrtc