diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-13 20:08:41 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-13 20:08:41 +0000 |
commit | ea0fb418e68bb4f9d501ea5787c3481c5e727e0e (patch) | |
tree | 00e47b33185d69771fbb6be624156141d2e4039c /content | |
parent | d7767b83fe99ad22e8b42c5cd08295b74e7b64c4 (diff) | |
download | chromium_src-ea0fb418e68bb4f9d501ea5787c3481c5e727e0e.zip chromium_src-ea0fb418e68bb4f9d501ea5787c3481c5e727e0e.tar.gz chromium_src-ea0fb418e68bb4f9d501ea5787c3481c5e727e0e.tar.bz2 |
The beginnings of unit tests for AudioDevice.
This adds a single test for AudioDevice and a skeleton for building more tests.
The next step will be to add more functional tests and a way to share worker threads across multiple AudioDevice instances.
BUG=none
TEST=Run content_unittests --gtest_filter=AudioDeviceTest.*
Review URL: https://chromiumcodereview.appspot.com/10695108
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146632 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/content_tests.gypi | 1 | ||||
-rw-r--r-- | content/renderer/media/audio_device.cc | 6 | ||||
-rw-r--r-- | content/renderer/media/audio_device.h | 22 | ||||
-rw-r--r-- | content/renderer/media/audio_device_factory.cc | 4 | ||||
-rw-r--r-- | content/renderer/media/audio_device_unittest.cc | 90 | ||||
-rw-r--r-- | content/renderer/media/audio_input_device.cc | 3 | ||||
-rw-r--r-- | content/renderer/media/audio_message_filter.h | 3 | ||||
-rw-r--r-- | content/renderer/media/scoped_loop_observer.cc | 5 | ||||
-rw-r--r-- | content/renderer/media/scoped_loop_observer.h | 5 |
9 files changed, 124 insertions, 15 deletions
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 299cf5a..520031b 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -323,6 +323,7 @@ 'renderer/android/email_detector_unittest.cc', 'renderer/android/phone_number_detector_unittest.cc', 'renderer/gpu/input_event_filter_unittest.cc', + 'renderer/media/audio_device_unittest.cc', 'renderer/media/audio_message_filter_unittest.cc', 'renderer/media/capture_video_decoder_unittest.cc', 'renderer/media/video_capture_impl_unittest.cc', diff --git a/content/renderer/media/audio_device.cc b/content/renderer/media/audio_device.cc index 7365bde..dcbd2b0 100644 --- a/content/renderer/media/audio_device.cc +++ b/content/renderer/media/audio_device.cc @@ -8,7 +8,6 @@ #include "base/message_loop.h" #include "base/threading/thread_restrictions.h" #include "base/time.h" -#include "content/common/child_process.h" #include "content/common/media/audio_messages.h" #include "content/common/view_messages.h" #include "media/audio/audio_output_controller.h" @@ -38,8 +37,9 @@ class AudioDevice::AudioThreadCallback DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); }; -AudioDevice::AudioDevice() - : ScopedLoopObserver(ChildProcess::current()->io_message_loop()), +AudioDevice::AudioDevice( + const scoped_refptr<base::MessageLoopProxy>& io_loop) + : ScopedLoopObserver(io_loop), callback_(NULL), volume_(1.0), stream_id_(0), diff --git a/content/renderer/media/audio_device.h b/content/renderer/media/audio_device.h index 657d82c..5f60411 100644 --- a/content/renderer/media/audio_device.h +++ b/content/renderer/media/audio_device.h @@ -79,6 +79,10 @@ namespace media { class AudioParameters; } +namespace content { +class AudioDeviceFactory; +} + class CONTENT_EXPORT AudioDevice : NON_EXPORTED_BASE(public media::AudioRendererSink), public AudioMessageFilter::Delegate, @@ -86,10 +90,6 @@ class CONTENT_EXPORT AudioDevice public: // Methods called on main render thread ------------------------------------- - // Creates an uninitialized AudioDevice. Clients must call Initialize() - // before using. - AudioDevice(); - // AudioRendererSink implementation. virtual void Initialize(const media::AudioParameters& params, RenderCallback* callback) OVERRIDE; @@ -107,12 +107,24 @@ class CONTENT_EXPORT AudioDevice base::SyncSocket::Handle socket_handle, uint32 length) OVERRIDE; - private: + protected: + friend class content::AudioDeviceFactory; + + // Creates an uninitialized AudioDevice. Clients must call Initialize() + // before using. The constructor is protected to ensure that the + // AudioDeviceFactory is always used for construction in Chrome. + // Tests should use a test class that inherits from AudioDevice to gain + // access to the constructor. + // TODO(tommi): When all dependencies on |content| have been removed + // from AudioDevice, move this class over to media/audio. + explicit AudioDevice(const scoped_refptr<base::MessageLoopProxy>& io_loop); + // Magic required by ref_counted.h to avoid any code deleting the object // accidentally while there are references to it. friend class base::RefCountedThreadSafe<AudioDevice>; virtual ~AudioDevice(); + private: // Methods called on IO thread ---------------------------------------------- // The following methods are tasks posted on the IO thread that needs to // be executed on that thread. They interact with AudioMessageFilter and diff --git a/content/renderer/media/audio_device_factory.cc b/content/renderer/media/audio_device_factory.cc index 555ebd6..ee7906f 100644 --- a/content/renderer/media/audio_device_factory.cc +++ b/content/renderer/media/audio_device_factory.cc @@ -5,6 +5,7 @@ #include "content/renderer/media/audio_device_factory.h" #include "base/logging.h" +#include "content/common/child_process.h" #include "content/renderer/media/audio_device.h" namespace content { @@ -17,7 +18,8 @@ media::AudioRendererSink* AudioDeviceFactory::Create() { if (factory_) { return factory_->CreateAudioDevice(); } - return new AudioDevice(); + return new AudioDevice( + ChildProcess::current()->io_message_loop()->message_loop_proxy()); } AudioDeviceFactory::AudioDeviceFactory() { diff --git a/content/renderer/media/audio_device_unittest.cc b/content/renderer/media/audio_device_unittest.cc new file mode 100644 index 0000000..6de54c1 --- /dev/null +++ b/content/renderer/media/audio_device_unittest.cc @@ -0,0 +1,90 @@ +// Copyright (c) 2012 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 <vector> + +#include "base/at_exit.h" +#include "base/message_loop.h" +#include "content/renderer/media/audio_device.h" +#include "content/renderer/media/audio_message_filter.h" +#include "media/audio/sample_rates.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// Derived from AudioDevice to gain access to the protected constructor. +class TestAudioDevice : public AudioDevice { + public: + explicit TestAudioDevice(const scoped_refptr<base::MessageLoopProxy>& io_loop) + : AudioDevice(io_loop) {} + + protected: + virtual ~TestAudioDevice() {} +}; + +class FakeRenderCallback : public media::AudioRendererSink::RenderCallback { + public: + FakeRenderCallback() {} + virtual ~FakeRenderCallback() {} + + virtual int Render(const std::vector<float*>& audio_data, + int number_of_frames, + int audio_delay_milliseconds) OVERRIDE { + NOTIMPLEMENTED(); + return 0; + } + + virtual void OnRenderError() OVERRIDE { + ADD_FAILURE(); + } +}; + +class FakeAudioMessageFilter : public AudioMessageFilter { + public: + FakeAudioMessageFilter() {} + + virtual bool Send(IPC::Message* message) { + // TODO(tommi): Override to simulate message passing. + NOTIMPLEMENTED(); + delete message; + return true; + } + + protected: + virtual ~FakeAudioMessageFilter() {} +}; + +} // namespace. + +class AudioDeviceTest : public testing::Test { + public: + AudioDeviceTest() {} + ~AudioDeviceTest() {} + + protected: + // Used to clean up TLS pointers that the test(s) will initialize. + // Must remain the first member of this class. + base::ShadowingAtExitManager at_exit_manager_; + MessageLoopForIO io_loop_; +}; + +// The simplest test for AudioDevice. Used to test construction of AudioDevice +// and that the runtime environment is set up correctly (e.g. ChildProcess and +// AudioMessageFilter global pointers). +TEST_F(AudioDeviceTest, Initialize) { + FakeRenderCallback callback; + media::AudioParameters audio_parameters( + media::AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, + media::k48000Hz, 16, 1024); + + // This sets a global audio_message_filter pointer. AudioDevice will pick + // up a pointer to this variable via the static AudioMessageFilter::Get() + // method. + scoped_refptr<FakeAudioMessageFilter> audio_message_filter = + new FakeAudioMessageFilter(); + + scoped_refptr<AudioDevice> audio_device( + new TestAudioDevice(io_loop_.message_loop_proxy())); + audio_device->Initialize(audio_parameters, &callback); +} diff --git a/content/renderer/media/audio_input_device.cc b/content/renderer/media/audio_input_device.cc index 8dcf8d7..da33e3a 100644 --- a/content/renderer/media/audio_input_device.cc +++ b/content/renderer/media/audio_input_device.cc @@ -40,7 +40,8 @@ class AudioInputDevice::AudioThreadCallback AudioInputDevice::AudioInputDevice(const media::AudioParameters& params, CaptureCallback* callback, CaptureEventHandler* event_handler) - : ScopedLoopObserver(ChildProcess::current()->io_message_loop()), + : ScopedLoopObserver( + ChildProcess::current()->io_message_loop()->message_loop_proxy()), audio_parameters_(params), callback_(callback), event_handler_(event_handler), diff --git a/content/renderer/media/audio_message_filter.h b/content/renderer/media/audio_message_filter.h index 099e9e1..efc80a7 100644 --- a/content/renderer/media/audio_message_filter.h +++ b/content/renderer/media/audio_message_filter.h @@ -48,7 +48,8 @@ class CONTENT_EXPORT AudioMessageFilter void RemoveDelegate(int32 id); // Sends an IPC message using |channel_|. - bool Send(IPC::Message* message); + // This method is virtual so that it can be overridden in tests. + virtual bool Send(IPC::Message* message); // IPC::ChannelProxy::MessageFilter override. Called on IO thread. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; diff --git a/content/renderer/media/scoped_loop_observer.cc b/content/renderer/media/scoped_loop_observer.cc index 1e02592..627ad6f 100644 --- a/content/renderer/media/scoped_loop_observer.cc +++ b/content/renderer/media/scoped_loop_observer.cc @@ -7,8 +7,9 @@ #include "base/bind.h" #include "base/synchronization/waitable_event.h" -ScopedLoopObserver::ScopedLoopObserver(MessageLoop* loop) - : loop_(loop->message_loop_proxy()) { +ScopedLoopObserver::ScopedLoopObserver( + const scoped_refptr<base::MessageLoopProxy>& loop) + : loop_(loop) { ObserveLoopDestruction(true, NULL); } diff --git a/content/renderer/media/scoped_loop_observer.h b/content/renderer/media/scoped_loop_observer.h index 46463e1..9875783 100644 --- a/content/renderer/media/scoped_loop_observer.h +++ b/content/renderer/media/scoped_loop_observer.h @@ -22,13 +22,14 @@ class WaitableEvent; class ScopedLoopObserver : public MessageLoop::DestructionObserver { public: - explicit ScopedLoopObserver(MessageLoop* message_loop); + explicit ScopedLoopObserver( + const scoped_refptr<base::MessageLoopProxy>& message_loop); protected: virtual ~ScopedLoopObserver(); // Accessor to the loop that's used by the derived class. - base::MessageLoopProxy* message_loop() { return loop_; } + const scoped_refptr<base::MessageLoopProxy>& message_loop() { return loop_; } private: // Call to add or remove ourselves from the list of destruction observers for |