summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc388
1 files changed, 388 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
new file mode 100644
index 00000000000..9d9ca8ea404
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
@@ -0,0 +1,388 @@
+// Copyright 2018 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 "third_party/blink/public/web/modules/peerconnection/transceiver_state_surfacer.h"
+
+#include <memory>
+#include <tuple>
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_util.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h"
+#include "third_party/blink/public/web/web_heap.h"
+
+using testing::AnyNumber;
+using testing::Return;
+
+namespace blink {
+
+// To avoid name collision on jumbo builds.
+namespace transceiver_state_surfacer_test {
+
+class MockSctpTransport : public webrtc::SctpTransportInterface {
+ public:
+ MOCK_CONST_METHOD0(dtls_transport,
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface>());
+ MOCK_CONST_METHOD0(Information, webrtc::SctpTransportInformation());
+ MOCK_METHOD1(RegisterObserver, void(webrtc::SctpTransportObserverInterface*));
+ MOCK_METHOD0(UnregisterObserver, void());
+};
+
+class TransceiverStateSurfacerTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
+ main_task_runner_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ track_adapter_map_ = new blink::WebRtcMediaStreamTrackAdapterMap(
+ dependency_factory_.get(), main_task_runner_);
+ surfacer_.reset(new TransceiverStateSurfacer(main_task_runner_,
+ signaling_task_runner()));
+ peer_connection_ = dependency_factory_->CreatePeerConnection(
+ webrtc::PeerConnectionInterface::RTCConfiguration(), nullptr, nullptr);
+ EXPECT_CALL(
+ *(static_cast<blink::MockPeerConnectionImpl*>(peer_connection_.get())),
+ GetSctpTransport())
+ .Times(AnyNumber());
+ }
+
+ void TearDown() override {
+ // Make sure posted tasks get a chance to execute or else the stuff is
+ // teared down while things are in flight.
+ base::RunLoop().RunUntilIdle();
+ blink::WebHeap::CollectAllGarbageForTesting();
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const {
+ return dependency_factory_->GetWebRtcSignalingTaskRunner();
+ }
+
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ CreateLocalTrackAndAdapter(const std::string& id) {
+ return track_adapter_map_->GetOrCreateLocalTrackAdapter(
+ CreateBlinkLocalTrack(id));
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpTransceiver> CreateWebRtcTransceiver(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> local_track,
+ const std::string& local_stream_id,
+ const std::string& remote_track_id,
+ const std::string& remote_stream_id,
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) {
+ rtc::scoped_refptr<blink::FakeRtpTransceiver> transceiver =
+ new rtc::RefCountedObject<blink::FakeRtpTransceiver>(
+ local_track->kind() == webrtc::MediaStreamTrackInterface::kAudioKind
+ ? cricket::MEDIA_TYPE_AUDIO
+ : cricket::MEDIA_TYPE_VIDEO,
+ CreateWebRtcSender(local_track, local_stream_id),
+ CreateWebRtcReceiver(remote_track_id, remote_stream_id),
+ base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv,
+ base::nullopt);
+ if (transport.get()) {
+ transceiver->SetTransport(transport);
+ }
+ return transceiver;
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpSender> CreateWebRtcSender(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ const std::string& stream_id) {
+ return new rtc::RefCountedObject<blink::FakeRtpSender>(
+ std::move(track), std::vector<std::string>({stream_id}));
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpReceiver> CreateWebRtcReceiver(
+ const std::string& track_id,
+ const std::string& stream_id) {
+ rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_track =
+ blink::MockWebRtcAudioTrack::Create(track_id).get();
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ new rtc::RefCountedObject<blink::MockMediaStream>(stream_id));
+ return new rtc::RefCountedObject<blink::FakeRtpReceiver>(
+ remote_track.get(),
+ std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
+ {remote_stream}));
+ }
+
+ // Initializes the surfacer on the signaling thread and signals the waitable
+ // event when done. The WaitableEvent's Wait() blocks the main thread until
+ // initialization occurs.
+ std::unique_ptr<base::WaitableEvent> AsyncInitializeSurfacerWithWaitableEvent(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers) {
+ std::unique_ptr<base::WaitableEvent> waitable_event(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
+ signaling_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &TransceiverStateSurfacerTest::
+ AsyncInitializeSurfacerWithWaitableEventOnSignalingThread,
+ base::Unretained(this), std::move(transceivers),
+ waitable_event.get()));
+ return waitable_event;
+ }
+
+ // Initializes the surfacer on the signaling thread and posts back to the main
+ // thread to execute the callback when done. The RunLoop quits after the
+ // callback is executed. Use the RunLoop's Run() method to allow the posted
+ // task (such as the callback) to be executed while waiting. The caller must
+ // let the loop Run() before destroying it.
+ std::unique_ptr<base::RunLoop> AsyncInitializeSurfacerWithCallback(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers,
+ base::OnceCallback<void()> callback) {
+ std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop());
+ signaling_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&TransceiverStateSurfacerTest::
+ AsyncInitializeSurfacerWithCallbackOnSignalingThread,
+ base::Unretained(this), std::move(transceivers),
+ std::move(callback), run_loop.get()));
+ return run_loop;
+ }
+
+ void ObtainStatesAndExpectInitialized(
+ rtc::scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver) {
+ // Inspect SCTP transport
+ auto sctp_snapshot = surfacer_->SctpTransportSnapshot();
+ EXPECT_EQ(peer_connection_->GetSctpTransport(), sctp_snapshot.transport);
+ if (peer_connection_->GetSctpTransport()) {
+ EXPECT_EQ(peer_connection_->GetSctpTransport()->dtls_transport(),
+ sctp_snapshot.sctp_transport_state.dtls_transport());
+ }
+ // Inspect transceivers
+ auto transceiver_states = surfacer_->ObtainStates();
+ EXPECT_EQ(1u, transceiver_states.size());
+ auto& transceiver_state = transceiver_states[0];
+ EXPECT_EQ(transceiver_state.webrtc_transceiver().get(),
+ webrtc_transceiver.get());
+ // Inspect sender states.
+ const auto& sender_state = transceiver_state.sender_state();
+ EXPECT_TRUE(sender_state);
+ EXPECT_TRUE(sender_state->is_initialized());
+ const auto& webrtc_sender = webrtc_transceiver->sender();
+ EXPECT_EQ(sender_state->webrtc_sender().get(), webrtc_sender.get());
+ EXPECT_TRUE(sender_state->track_ref()->is_initialized());
+ EXPECT_EQ(sender_state->track_ref()->webrtc_track(),
+ webrtc_sender->track().get());
+ EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids());
+ EXPECT_EQ(sender_state->webrtc_dtls_transport(),
+ webrtc_sender->dtls_transport());
+ if (webrtc_sender->dtls_transport()) {
+ EXPECT_EQ(webrtc_sender->dtls_transport()->Information().state(),
+ sender_state->webrtc_dtls_transport_information().state());
+ } else {
+ EXPECT_EQ(webrtc::DtlsTransportState::kNew,
+ sender_state->webrtc_dtls_transport_information().state());
+ }
+ // Inspect receiver states.
+ const auto& receiver_state = transceiver_state.receiver_state();
+ EXPECT_TRUE(receiver_state);
+ EXPECT_TRUE(receiver_state->is_initialized());
+ const auto& webrtc_receiver = webrtc_transceiver->receiver();
+ EXPECT_EQ(receiver_state->webrtc_receiver().get(), webrtc_receiver.get());
+ EXPECT_TRUE(receiver_state->track_ref()->is_initialized());
+ EXPECT_EQ(receiver_state->track_ref()->webrtc_track(),
+ webrtc_receiver->track().get());
+ std::vector<std::string> receiver_stream_ids;
+ for (const auto& stream : webrtc_receiver->streams()) {
+ receiver_stream_ids.push_back(stream->id());
+ }
+ EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids);
+ EXPECT_EQ(receiver_state->webrtc_dtls_transport(),
+ webrtc_receiver->dtls_transport());
+ if (webrtc_receiver->dtls_transport()) {
+ EXPECT_EQ(webrtc_receiver->dtls_transport()->Information().state(),
+ receiver_state->webrtc_dtls_transport_information().state());
+ } else {
+ EXPECT_EQ(webrtc::DtlsTransportState::kNew,
+ receiver_state->webrtc_dtls_transport_information().state());
+ }
+ // Inspect transceiver states.
+ EXPECT_TRUE(blink::OptionalEquals(transceiver_state.mid(),
+ webrtc_transceiver->mid()));
+ EXPECT_EQ(transceiver_state.stopped(), webrtc_transceiver->stopped());
+ EXPECT_TRUE(transceiver_state.direction() ==
+ webrtc_transceiver->direction());
+ EXPECT_TRUE(blink::OptionalEquals(transceiver_state.current_direction(),
+ webrtc_transceiver->current_direction()));
+ }
+
+ private:
+ blink::WebMediaStreamTrack CreateBlinkLocalTrack(const std::string& id) {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(
+ blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio,
+ blink::WebString::FromUTF8("local_audio_track"), false);
+ blink::MediaStreamAudioSource* audio_source =
+ new blink::MediaStreamAudioSource(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting(), true);
+ // Takes ownership of |audio_source|.
+ web_source.SetPlatformSource(base::WrapUnique(audio_source));
+
+ blink::WebMediaStreamTrack web_track;
+ web_track.Initialize(web_source.Id(), web_source);
+ audio_source->ConnectToTrack(web_track);
+ return web_track;
+ }
+
+ void AsyncInitializeSurfacerWithWaitableEventOnSignalingThread(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers,
+ base::WaitableEvent* waitable_event) {
+ DCHECK(signaling_task_runner()->BelongsToCurrentThread());
+ surfacer_->Initialize(peer_connection_, track_adapter_map_,
+ std::move(transceivers));
+ waitable_event->Signal();
+ }
+
+ void AsyncInitializeSurfacerWithCallbackOnSignalingThread(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers,
+ base::OnceCallback<void()> callback,
+ base::RunLoop* run_loop) {
+ DCHECK(signaling_task_runner()->BelongsToCurrentThread());
+ surfacer_->Initialize(peer_connection_, track_adapter_map_,
+ std::move(transceivers));
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&TransceiverStateSurfacerTest::
+ AsyncInitializeSurfacerWithCallbackOnMainThread,
+ base::Unretained(this), std::move(callback), run_loop));
+ }
+
+ void AsyncInitializeSurfacerWithCallbackOnMainThread(
+ base::OnceCallback<void()> callback,
+ base::RunLoop* run_loop) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(surfacer_->is_initialized());
+ std::move(callback).Run();
+ run_loop->Quit();
+ }
+
+ protected:
+ scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
+ dependency_factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_adapter_map_;
+ std::unique_ptr<TransceiverStateSurfacer> surfacer_;
+};
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverBlockingly) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", nullptr);
+ auto waitable_event =
+ AsyncInitializeSurfacerWithWaitableEvent({webrtc_transceiver});
+ waitable_event->Wait();
+ ObtainStatesAndExpectInitialized(webrtc_transceiver);
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverInCallback) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", nullptr);
+ auto run_loop = AsyncInitializeSurfacerWithCallback(
+ {webrtc_transceiver},
+ base::BindOnce(
+ &TransceiverStateSurfacerTest::ObtainStatesAndExpectInitialized,
+ base::Unretained(this), webrtc_transceiver));
+ run_loop->Run();
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverWithTransport) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", new rtc::RefCountedObject<blink::FakeDtlsTransport>());
+ auto run_loop = AsyncInitializeSurfacerWithCallback(
+ {webrtc_transceiver},
+ base::BindOnce(
+ &TransceiverStateSurfacerTest::ObtainStatesAndExpectInitialized,
+ base::Unretained(this), webrtc_transceiver));
+ run_loop->Run();
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceSenderStateOnly) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_sender =
+ CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream");
+ auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent(
+ {new SurfaceSenderStateOnly(webrtc_sender)});
+ waitable_event->Wait();
+ auto transceiver_states = surfacer_->ObtainStates();
+ EXPECT_EQ(1u, transceiver_states.size());
+ auto& transceiver_state = transceiver_states[0];
+ EXPECT_TRUE(transceiver_state.sender_state());
+ EXPECT_TRUE(transceiver_state.sender_state()->is_initialized());
+ EXPECT_FALSE(transceiver_state.receiver_state());
+ // Expect transceiver members be be missing for optional members and have
+ // sensible values for non-optional members.
+ EXPECT_FALSE(transceiver_state.mid());
+ EXPECT_FALSE(transceiver_state.stopped());
+ EXPECT_EQ(transceiver_state.direction(),
+ webrtc::RtpTransceiverDirection::kSendOnly);
+ EXPECT_FALSE(transceiver_state.current_direction());
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceReceiverStateOnly) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_receiver = CreateWebRtcReceiver("remote_track", "remote_stream");
+ auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent(
+ {new SurfaceReceiverStateOnly(webrtc_receiver)});
+ waitable_event->Wait();
+ auto transceiver_states = surfacer_->ObtainStates();
+ EXPECT_EQ(1u, transceiver_states.size());
+ auto& transceiver_state = transceiver_states[0];
+ EXPECT_FALSE(transceiver_state.sender_state());
+ EXPECT_TRUE(transceiver_state.receiver_state());
+ EXPECT_TRUE(transceiver_state.receiver_state()->is_initialized());
+ // Expect transceiver members be be missing for optional members and have
+ // sensible values for non-optional members.
+ EXPECT_FALSE(transceiver_state.mid());
+ EXPECT_FALSE(transceiver_state.stopped());
+ EXPECT_EQ(transceiver_state.direction(),
+ webrtc::RtpTransceiverDirection::kRecvOnly);
+ EXPECT_FALSE(transceiver_state.current_direction());
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverWithSctpTransport) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", nullptr);
+ rtc::scoped_refptr<MockSctpTransport> mock_sctp_transport =
+ new rtc::RefCountedObject<MockSctpTransport>();
+ webrtc::SctpTransportInformation sctp_transport_info(
+ webrtc::SctpTransportState::kNew);
+ EXPECT_CALL(
+ *(static_cast<blink::MockPeerConnectionImpl*>(peer_connection_.get())),
+ GetSctpTransport())
+ .WillRepeatedly(Return(mock_sctp_transport));
+ EXPECT_CALL(*mock_sctp_transport.get(), Information())
+ .WillRepeatedly(Return(sctp_transport_info));
+ EXPECT_CALL(*mock_sctp_transport.get(), dtls_transport()).Times(AnyNumber());
+ auto waitable_event =
+ AsyncInitializeSurfacerWithWaitableEvent({webrtc_transceiver});
+ waitable_event->Wait();
+ EXPECT_TRUE(surfacer_->SctpTransportSnapshot().transport);
+ ObtainStatesAndExpectInitialized(webrtc_transceiver);
+}
+
+} // namespace transceiver_state_surfacer_test
+} // namespace blink