Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(508)

Unified Diff: content/renderer/media/audio_ipc_factory_unittest.cc

Issue 2890753003: Introduce AudioIPCFactory. (Closed)
Patch Set: Dale's comments. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/renderer/media/audio_ipc_factory.cc ('k') | content/renderer/pepper/pepper_platform_audio_output.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/media/audio_ipc_factory_unittest.cc
diff --git a/content/renderer/media/audio_ipc_factory_unittest.cc b/content/renderer/media/audio_ipc_factory_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..166e8409483f7079e19005313a7ea7250c7e90cc
--- /dev/null
+++ b/content/renderer/media/audio_ipc_factory_unittest.cc
@@ -0,0 +1,223 @@
+// Copyright 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/audio_ipc_factory.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/message_loop/message_loop.h"
+#include "base/threading/thread.h"
+#include "content/renderer/media/audio_message_filter.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace content {
+
+namespace {
+
+const int kRenderFrameId = 0;
+
+std::unique_ptr<base::Thread> MakeIOThread() {
+ auto io_thread = base::MakeUnique<base::Thread>("test IO thread");
+ base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
+ CHECK(io_thread->StartWithOptions(thread_options));
+ return io_thread;
+}
+
+class FakeRemoteFactory : public mojom::RendererAudioOutputStreamFactory {
+ public:
+ FakeRemoteFactory() : binding_(this) {}
+ ~FakeRemoteFactory() override {}
+
+ void RequestDeviceAuthorization(
+ media::mojom::AudioOutputStreamProviderRequest stream_provider,
+ int64_t session_id,
+ const std::string& device_id,
+ RequestDeviceAuthorizationCallback callback) override {
+ std::move(callback).Run(
+ media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
+ media::AudioParameters::UnavailableDeviceParams(), std::string());
+ EXPECT_FALSE(on_called_.is_null());
+ std::move(on_called_).Run();
+ }
+
+ void SetOnCalledCallback(base::OnceClosure on_called) {
+ on_called_ = std::move(on_called);
+ }
+
+ void Bind(mojo::ScopedMessagePipeHandle handle) {
+ EXPECT_FALSE(binding_.is_bound());
+ binding_.Bind(
+ mojo::InterfaceRequest<mojom::RendererAudioOutputStreamFactory>(
+ std::move(handle)));
+ }
+
+ private:
+ mojo::Binding<mojom::RendererAudioOutputStreamFactory> binding_;
+ base::OnceClosure on_called_;
+};
+
+class FakeAudioIPCDelegate : public media::AudioOutputIPCDelegate {
+ void OnError() override {}
+ void OnDeviceAuthorized(media::OutputDeviceStatus device_status,
+ const media::AudioParameters& output_params,
+ const std::string& matched_device_id) override {}
+ void OnStreamCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle socket_handle,
+ int length) override {}
+ void OnIPCClosed() override {}
+};
+
+} // namespace
+
+class AudioIPCFactoryTest : public testing::Test {
+ public:
+ AudioIPCFactoryTest() {}
+ ~AudioIPCFactoryTest() override {}
+
+ void RequestAuthorizationOnIOThread(
+ std::unique_ptr<media::AudioOutputIPC> output_ipc) {
+ output_ipc->RequestDeviceAuthorization(&fake_delegate, 0, "",
+ url::Origin());
+
+ output_ipc->CloseStream();
+ }
+
+ private:
+ FakeAudioIPCDelegate fake_delegate;
+};
+
+TEST_F(AudioIPCFactoryTest, CallFactoryFromIOThread) {
+ // This test makes sure that AudioIPCFactory correctly binds the
+ // RendererAudioOutputStreamFactoryPtr to the IO thread.
+ base::MessageLoop message_loop;
+ base::RunLoop run_loop;
+ auto io_thread = MakeIOThread();
+
+ FakeRemoteFactory remote_factory;
+ remote_factory.SetOnCalledCallback(run_loop.QuitWhenIdleClosure());
+
+ service_manager::InterfaceProvider interface_provider;
+ service_manager::InterfaceProvider::TestApi(&interface_provider)
+ .SetBinderForName(mojom::RendererAudioOutputStreamFactory::Name_,
+ base::BindRepeating(&FakeRemoteFactory::Bind,
+ base::Unretained(&remote_factory)));
+
+ AudioIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+
+ ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId, &interface_provider);
+
+ // To make sure that the pointer stored in |ipc_factory| is connected to
+ // |remote_factory|, and also that it's bound to |io_thread|, we create an
+ // AudioOutputIPC object and request device authorization on the IO thread.
+ // This is supposed to call |remote_factory| on the main thread.
+ io_thread->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AudioIPCFactoryTest::RequestAuthorizationOnIOThread,
+ base::Unretained(this),
+ ipc_factory.CreateAudioOutputIPC(kRenderFrameId)));
+
+ // Wait for call to |remote_factory|:
+ run_loop.Run();
+
+ ipc_factory.MaybeDeregisterRemoteFactory(0);
+
+ io_thread.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AudioIPCFactoryTest, SeveralFactories) {
+ // This test simulates having several frames being created and destructed.
+ base::MessageLoop message_loop;
+ auto io_thread = MakeIOThread();
+ const int n_factories = 5;
+
+ std::vector<service_manager::InterfaceProvider> interface_providers(
+ n_factories);
+
+ std::vector<FakeRemoteFactory> remote_factories(n_factories);
+
+ for (size_t i = 0; i < n_factories; i++) {
+ service_manager::InterfaceProvider::TestApi(&interface_providers[i])
+ .SetBinderForName(
+ mojom::RendererAudioOutputStreamFactory::Name_,
+ base::BindRepeating(&FakeRemoteFactory::Bind,
+ base::Unretained(&remote_factories[i])));
+ }
+
+ base::RunLoop().RunUntilIdle();
+
+ AudioIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+
+ for (size_t i = 0; i < n_factories; i++) {
+ ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId + i,
+ &interface_providers[i]);
+ }
+
+ base::RunLoop run_loop;
+ remote_factories[0].SetOnCalledCallback(run_loop.QuitWhenIdleClosure());
+ io_thread->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AudioIPCFactoryTest::RequestAuthorizationOnIOThread,
+ base::Unretained(this),
+ ipc_factory.CreateAudioOutputIPC(kRenderFrameId)));
+ run_loop.Run();
+
+ // Do some operation and make sure the internal state isn't messed up:
+ ipc_factory.MaybeDeregisterRemoteFactory(1);
+
+ base::RunLoop run_loop2;
+ remote_factories[2].SetOnCalledCallback(run_loop2.QuitWhenIdleClosure());
+ io_thread->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AudioIPCFactoryTest::RequestAuthorizationOnIOThread,
+ base::Unretained(this),
+ ipc_factory.CreateAudioOutputIPC(kRenderFrameId + 2)));
+ run_loop2.Run();
+
+ for (size_t i = 0; i < n_factories; i++) {
+ if (i == 1)
+ continue;
+ ipc_factory.MaybeDeregisterRemoteFactory(i);
+ }
+
+ io_thread.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AudioIPCFactoryTest, RegisterDeregisterBackToBack_Deregisters) {
+ // This test makes sure that calling Register... followed by Deregister...
+ // correctly sequences the registration before the deregistration.
+ base::MessageLoop message_loop;
+ auto io_thread = MakeIOThread();
+
+ FakeRemoteFactory remote_factory;
+
+ service_manager::InterfaceProvider interface_provider;
+ service_manager::InterfaceProvider::TestApi(&interface_provider)
+ .SetBinderForName(mojom::RendererAudioOutputStreamFactory::Name_,
+ base::BindRepeating(&FakeRemoteFactory::Bind,
+ base::Unretained(&remote_factory)));
+
+ AudioIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+
+ ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId, &interface_provider);
+ ipc_factory.MaybeDeregisterRemoteFactory(kRenderFrameId);
+ // That there is no factory remaining at destruction is DCHECKed in the
+ // AudioIPCFactory destructor.
+
+ base::RunLoop().RunUntilIdle();
+ io_thread.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
+} // namespace content
« no previous file with comments | « content/renderer/media/audio_ipc_factory.cc ('k') | content/renderer/pepper/pepper_platform_audio_output.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698