summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-13 20:08:41 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-13 20:08:41 +0000
commitea0fb418e68bb4f9d501ea5787c3481c5e727e0e (patch)
tree00e47b33185d69771fbb6be624156141d2e4039c /content
parentd7767b83fe99ad22e8b42c5cd08295b74e7b64c4 (diff)
downloadchromium_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.gypi1
-rw-r--r--content/renderer/media/audio_device.cc6
-rw-r--r--content/renderer/media/audio_device.h22
-rw-r--r--content/renderer/media/audio_device_factory.cc4
-rw-r--r--content/renderer/media/audio_device_unittest.cc90
-rw-r--r--content/renderer/media/audio_input_device.cc3
-rw-r--r--content/renderer/media/audio_message_filter.h3
-rw-r--r--content/renderer/media/scoped_loop_observer.cc5
-rw-r--r--content/renderer/media/scoped_loop_observer.h5
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