blob: 4c1734020464b57efcf753ef7720415dc14de087 [file] [log] [blame]
// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/webrtc/peer_connection_tracker.h"
#include "base/test/scoped_task_environment.h"
#include "content/common/media/peer_connection_tracker.mojom.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/test/mock_render_thread.h"
#include "content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h"
#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
#include "ipc/ipc_message_macros.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_rtc_offer_options.h"
#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
#include "third_party/blink/public/platform/web_rtc_rtp_sender.h"
#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
using ::testing::_;
namespace content {
const char* kDefaultTransceiverString =
"getTransceivers()[0]:{\n"
" mid:null,\n"
" sender:{\n"
" track:'senderTrackId',\n"
" streams:['senderStreamId'],\n"
" },\n"
" receiver:{\n"
" track:'receiverTrackId',\n"
" streams:['receiverStreamId'],\n"
" },\n"
" stopped:false,\n"
" direction:'sendonly',\n"
" currentDirection:null,\n"
"}";
const char* kDefaultSenderString =
"getSenders()[0]:{\n"
" track:'senderTrackId',\n"
" streams:['senderStreamId'],\n"
"}";
const char* kDefaultReceiverString =
"getReceivers()[0]:{\n"
" track:'receiverTrackId',\n"
" streams:['receiverStreamId'],\n"
"}";
class MockPeerConnectionTrackerHost : public mojom::PeerConnectionTrackerHost {
public:
MockPeerConnectionTrackerHost() : binding_(this) {}
MOCK_METHOD3(UpdatePeerConnection,
void(int, const std::string&, const std::string&));
MOCK_METHOD1(RemovePeerConnection, void(int));
MOCK_METHOD2(OnPeerConnectionSessionIdSet, void(int, const std::string&));
MOCK_METHOD5(GetUserMedia,
void(const std::string&,
bool,
bool,
const std::string&,
const std::string&));
MOCK_METHOD2(WebRtcEventLogWrite, void(int, const std::string&));
mojom::PeerConnectionTrackerHostAssociatedPtr CreateInterfacePtrAndBind() {
mojom::PeerConnectionTrackerHostAssociatedPtr
peer_connection_tracker_host_ptr_;
binding_.Bind(mojo::MakeRequestAssociatedWithDedicatedPipe(
&peer_connection_tracker_host_ptr_),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
return peer_connection_tracker_host_ptr_;
}
mojo::AssociatedBinding<mojom::PeerConnectionTrackerHost> binding_;
};
// Creates a transceiver that is expected to be logged as
// |kDefaultTransceiverString|, |kDefaultSenderString| or
// |kDefaultReceiverString| depending on if |implementation_type| refers to a
// fully implemented, sender-only or receiver-only transceiver.
//
// This is used in unittests that don't care about the specific attributes of
// the transceiver.
std::unique_ptr<blink::WebRTCRtpTransceiver> CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType implementation_type) {
std::unique_ptr<blink::WebRTCRtpTransceiver> transceiver;
FakeRTCRtpSender sender("senderTrackId", {"senderStreamId"});
FakeRTCRtpReceiver receiver("receiverTrackId", {"receiverStreamId"});
if (implementation_type ==
blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) {
transceiver = std::make_unique<FakeRTCRtpTransceiver>(
base::nullopt, std::move(sender), std::move(receiver),
false /* stopped */,
webrtc::RtpTransceiverDirection::kSendOnly /* direction */,
base::nullopt /* current_direction */);
} else if (implementation_type ==
blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) {
transceiver = std::make_unique<RTCRtpSenderOnlyTransceiver>(
std::make_unique<FakeRTCRtpSender>(sender));
} else {
DCHECK_EQ(
implementation_type,
blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly);
transceiver = std::make_unique<RTCRtpReceiverOnlyTransceiver>(
std::make_unique<FakeRTCRtpReceiver>(receiver));
}
return transceiver;
}
namespace {
class MockSendTargetThread : public MockRenderThread {
public:
MOCK_METHOD1(OnAddPeerConnection, void(PeerConnectionInfo));
private:
bool OnMessageReceived(const IPC::Message& msg) override;
};
bool MockSendTargetThread::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MockSendTargetThread, msg)
IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_AddPeerConnection,
OnAddPeerConnection)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
// TODO(https://crbug.com/868868): Move this into a separate file.
class MockPeerConnectionHandler : public RTCPeerConnectionHandler {
public:
MockPeerConnectionHandler()
: RTCPeerConnectionHandler(
&client_,
&dependency_factory_,
blink::scheduler::GetSingleThreadTaskRunnerForTesting()) {}
MOCK_METHOD0(CloseClientPeerConnection, void());
private:
MockPeerConnectionDependencyFactory dependency_factory_;
MockWebRTCPeerConnectionHandlerClient client_;
};
class PeerConnectionTrackerTest : public ::testing::Test {
public:
void CreateTrackerWithMocks() {
mock_host_.reset(new MockPeerConnectionTrackerHost());
tracker_.reset(new PeerConnectionTracker(
mock_host_->CreateInterfacePtrAndBind(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting()));
target_thread_.reset(new MockSendTargetThread());
tracker_->OverrideSendTargetForTesting(target_thread_.get());
}
void CreateAndRegisterPeerConnectionHandler() {
mock_handler_.reset(new MockPeerConnectionHandler());
EXPECT_CALL(*target_thread_, OnAddPeerConnection(_));
tracker_->RegisterPeerConnection(
mock_handler_.get(),
webrtc::PeerConnectionInterface::RTCConfiguration(),
blink::WebMediaConstraints(), nullptr);
}
protected:
base::test::ScopedTaskEnvironment task_environment_;
std::unique_ptr<MockPeerConnectionTrackerHost> mock_host_;
std::unique_ptr<PeerConnectionTracker> tracker_;
std::unique_ptr<MockSendTargetThread> target_thread_;
std::unique_ptr<MockPeerConnectionHandler> mock_handler_;
};
} // namespace
TEST_F(PeerConnectionTrackerTest, CreatingObject) {
PeerConnectionTracker tracker(
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
}
TEST_F(PeerConnectionTrackerTest, TrackCreateOffer) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
// Note: blink::WebRTCOfferOptions is not mockable. So we can't write tests
// for anything but a null options parameter.
blink::WebRTCOfferOptions options(0, 0, false, false);
EXPECT_CALL(*mock_host_,
UpdatePeerConnection(
_, "createOffer",
"options: {offerToReceiveVideo: 0, offerToReceiveAudio: 0, "
"voiceActivityDetection: false, iceRestart: false}"));
tracker_->TrackCreateOffer(mock_handler_.get(), options);
base::RunLoop().RunUntilIdle();
}
TEST_F(PeerConnectionTrackerTest, OnSuspend) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
EXPECT_CALL(*mock_handler_, CloseClientPeerConnection());
std::unique_ptr<IPC::Message> message(new PeerConnectionTracker_OnSuspend());
tracker_->OnControlMessageReceived(*message.get());
}
TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesPresent) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
FakeRTCRtpTransceiver transceiver(
"midValue", FakeRTCRtpSender("senderTrackId", {"streamIdA", "streamIdB"}),
FakeRTCRtpReceiver("receiverTrackId", {"streamIdC"}), true /* stopped */,
webrtc::RtpTransceiverDirection::kSendRecv /* direction */,
webrtc::RtpTransceiverDirection::kInactive /* current_direction */);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverAdded", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackAddTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, transceiver,
0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: addTrack\n"
"\n"
"getTransceivers()[0]:{\n"
" mid:'midValue',\n"
" sender:{\n"
" track:'senderTrackId',\n"
" streams:['streamIdA','streamIdB'],\n"
" },\n"
" receiver:{\n"
" track:'receiverTrackId',\n"
" streams:['streamIdC'],\n"
" },\n"
" stopped:true,\n"
" direction:'sendrecv',\n"
" currentDirection:'inactive',\n"
"}",
update_value);
}
TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesNull) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
FakeRTCRtpTransceiver transceiver(
base::nullopt, FakeRTCRtpSender(base::nullopt, {}),
FakeRTCRtpReceiver("receiverTrackId", {}), false /* stopped */,
webrtc::RtpTransceiverDirection::kInactive /* direction */,
base::nullopt /* current_direction */);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverAdded", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackAddTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kAddTransceiver,
transceiver, 1u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: addTransceiver\n"
"\n"
"getTransceivers()[1]:{\n"
" mid:null,\n"
" sender:{\n"
" track:null,\n"
" streams:[],\n"
" },\n"
" receiver:{\n"
" track:'receiverTrackId',\n"
" streams:[],\n"
" },\n"
" stopped:false,\n"
" direction:'inactive',\n"
" currentDirection:null,\n"
"}",
update_value);
}
TEST_F(PeerConnectionTrackerTest, ModifyTransceiver) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto transceiver = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverModified", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackModifyTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription,
*transceiver, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: setLocalDescription\n"
"\n" +
std::string(kDefaultTransceiverString),
update_value);
}
TEST_F(PeerConnectionTrackerTest, RemoveTransceiver) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto transceiver = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverRemoved", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackRemoveTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack,
*transceiver, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: removeTrack\n"
"\n" +
std::string(kDefaultTransceiverString),
update_value);
}
TEST_F(PeerConnectionTrackerTest, AddSender) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto sender_only = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderAdded", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackAddTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription,
*sender_only, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: setLocalDescription\n"
"\n" +
std::string(kDefaultSenderString),
update_value);
}
TEST_F(PeerConnectionTrackerTest, ModifySender) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto sender_only = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderModified", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackModifyTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
*sender_only, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: setRemoteDescription\n"
"\n" +
std::string(kDefaultSenderString),
update_value);
}
TEST_F(PeerConnectionTrackerTest, RemoveSender) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto sender_only = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderRemoved", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackRemoveTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
*sender_only, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: setRemoteDescription\n"
"\n" +
std::string(kDefaultSenderString),
update_value);
}
TEST_F(PeerConnectionTrackerTest, AddReceiver) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto receiver_only = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverAdded", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackAddTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
*receiver_only, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: setRemoteDescription\n"
"\n" +
std::string(kDefaultReceiverString),
update_value);
}
TEST_F(PeerConnectionTrackerTest, ModifyReceiver) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto receiver_only = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverModified", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackModifyTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
*receiver_only, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: setRemoteDescription\n"
"\n" +
std::string(kDefaultReceiverString),
update_value);
}
TEST_F(PeerConnectionTrackerTest, RemoveReceiver) {
CreateTrackerWithMocks();
CreateAndRegisterPeerConnectionHandler();
auto receiver_only = CreateDefaultTransceiver(
blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly);
std::string update_value;
EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverRemoved", _))
.WillOnce(testing::SaveArg<2>(&update_value));
tracker_->TrackRemoveTransceiver(
mock_handler_.get(),
PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
*receiver_only, 0u);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
"Caused by: setRemoteDescription\n"
"\n" +
std::string(kDefaultReceiverString),
update_value);
}
// TODO(hta): Write tests for the other tracking functions.
} // namespace