blob: c2f7dc786b0bb6858dee57956bc3b4762fe86f20 [file] [log] [blame]
// Copyright (c) 2017 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/webrtc_set_description_observer.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/child/child_process.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/mock_peer_connection_impl.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.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/web/web_heap.h"
#include "third_party/webrtc/api/peerconnectioninterface.h"
#include "third_party/webrtc/media/base/fakemediaengine.h"
#include "third_party/webrtc/pc/test/mock_peerconnection.h"
using ::testing::Return;
namespace content {
class WebRtcSetDescriptionObserverForTest
: public WebRtcSetDescriptionObserver {
public:
bool called() const { return called_; }
const WebRtcSetDescriptionObserver::States& states() const {
DCHECK(called_);
return states_;
}
const webrtc::RTCError& error() const {
DCHECK(called_);
return error_;
}
// WebRtcSetDescriptionObserver implementation.
void OnSetDescriptionComplete(
webrtc::RTCError error,
WebRtcSetDescriptionObserver::States states) override {
called_ = true;
error_ = std::move(error);
states_ = std::move(states);
}
private:
~WebRtcSetDescriptionObserverForTest() override {}
bool called_ = false;
webrtc::RTCError error_;
WebRtcSetDescriptionObserver::States states_;
};
// TODO(hbos): This only tests WebRtcSetRemoteDescriptionObserverHandler,
// parameterize the test to make it also test
// WebRtcSetLocalDescriptionObserverHandler and with "surface_receivers_only" as
// both true and false. https://crbug.com/865006
class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test {
public:
void SetUp() override {
pc_ = new webrtc::MockPeerConnection(new webrtc::FakePeerConnectionFactory(
std::unique_ptr<cricket::MediaEngineInterface>(
new cricket::FakeMediaEngine())));
dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> map =
new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(),
main_thread_);
observer_ = new WebRtcSetDescriptionObserverForTest();
observer_handler_ = WebRtcSetRemoteDescriptionObserverHandler::Create(
main_thread_, dependency_factory_->GetWebRtcSignalingThread(), pc_, map,
observer_, true /* surface_receivers_only*/);
}
void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); }
void InvokeOnSetRemoteDescriptionComplete(webrtc::RTCError error) {
base::RunLoop run_loop;
dependency_factory_->GetWebRtcSignalingThread()->PostTask(
FROM_HERE,
base::BindOnce(
&WebRtcSetRemoteDescriptionObserverHandlerTest::
InvokeOnSetRemoteDescriptionCompleteOnSignalingThread,
base::Unretained(this), std::move(error),
base::Unretained(&run_loop)));
run_loop.Run();
}
protected:
void InvokeOnSetRemoteDescriptionCompleteOnSignalingThread(
webrtc::RTCError error,
base::RunLoop* run_loop) {
observer_handler_->OnSetRemoteDescriptionComplete(std::move(error));
run_loop->Quit();
}
// The ScopedTaskEnvironment prevents the ChildProcess from leaking a
// TaskScheduler.
base::test::ScopedTaskEnvironment scoped_task_environment_;
ChildProcess child_process_;
scoped_refptr<webrtc::MockPeerConnection> pc_;
std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
scoped_refptr<WebRtcSetDescriptionObserverForTest> observer_;
scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> observer_handler_;
std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> receivers_;
};
TEST_F(WebRtcSetRemoteDescriptionObserverHandlerTest, OnSuccess) {
scoped_refptr<MockWebRtcAudioTrack> added_track =
MockWebRtcAudioTrack::Create("added_track");
scoped_refptr<webrtc::MediaStreamInterface> added_stream(
new rtc::RefCountedObject<MockMediaStream>("added_stream"));
scoped_refptr<webrtc::RtpReceiverInterface> added_receiver(
new rtc::RefCountedObject<FakeRtpReceiver>(
added_track.get(),
std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
{added_stream.get()})));
receivers_.push_back(added_receiver.get());
EXPECT_CALL(*pc_, signaling_state())
.WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable));
EXPECT_CALL(*pc_, GetReceivers()).WillRepeatedly(Return(receivers_));
InvokeOnSetRemoteDescriptionComplete(webrtc::RTCError::OK());
EXPECT_TRUE(observer_->called());
EXPECT_TRUE(observer_->error().ok());
EXPECT_EQ(webrtc::PeerConnectionInterface::kStable,
observer_->states().signaling_state);
EXPECT_EQ(1u, observer_->states().transceiver_states.size());
const RtpTransceiverState& transceiver_state =
observer_->states().transceiver_states[0];
EXPECT_FALSE(transceiver_state.sender_state());
EXPECT_TRUE(transceiver_state.receiver_state());
const RtpReceiverState& receiver_state = *transceiver_state.receiver_state();
EXPECT_EQ(added_receiver, receiver_state.webrtc_receiver());
EXPECT_EQ(added_track, receiver_state.track_ref()->webrtc_track());
EXPECT_EQ(1u, receiver_state.stream_ids().size());
EXPECT_EQ(added_stream->id(), receiver_state.stream_ids()[0]);
}
TEST_F(WebRtcSetRemoteDescriptionObserverHandlerTest, OnFailure) {
scoped_refptr<MockWebRtcAudioTrack> added_track =
MockWebRtcAudioTrack::Create("added_track");
scoped_refptr<webrtc::MediaStreamInterface> added_stream(
new rtc::RefCountedObject<MockMediaStream>("added_stream"));
scoped_refptr<webrtc::RtpReceiverInterface> added_receiver(
new rtc::RefCountedObject<FakeRtpReceiver>(
added_track.get(),
std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
{added_stream.get()})));
receivers_.push_back(added_receiver.get());
EXPECT_CALL(*pc_, signaling_state())
.WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable));
EXPECT_CALL(*pc_, GetReceivers()).WillRepeatedly(Return(receivers_));
InvokeOnSetRemoteDescriptionComplete(
webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER, "Oh noes!"));
EXPECT_TRUE(observer_->called());
EXPECT_FALSE(observer_->error().ok());
EXPECT_EQ(std::string("Oh noes!"), observer_->error().message());
// Verify states were surfaced even though we got an error.
EXPECT_EQ(webrtc::PeerConnectionInterface::kStable,
observer_->states().signaling_state);
EXPECT_EQ(1u, observer_->states().transceiver_states.size());
const RtpTransceiverState& transceiver_state =
observer_->states().transceiver_states[0];
EXPECT_FALSE(transceiver_state.sender_state());
EXPECT_TRUE(transceiver_state.receiver_state());
const RtpReceiverState& receiver_state = *transceiver_state.receiver_state();
EXPECT_EQ(added_receiver, receiver_state.webrtc_receiver());
EXPECT_EQ(added_track, receiver_state.track_ref()->webrtc_track());
EXPECT_EQ(1u, receiver_state.stream_ids().size());
EXPECT_EQ(added_stream->id(), receiver_state.stream_ids()[0]);
}
} // namespace content