diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-10 21:40:12 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-10 21:40:12 +0000 |
commit | 551acd620a1bc5c48efa05b4119bf90d940279d8 (patch) | |
tree | 61857e34400819e5b889fdfd0bdc5932686c73bb | |
parent | a3854295eb15b8b80035d5054c937971dd620674 (diff) | |
download | chromium_src-551acd620a1bc5c48efa05b4119bf90d940279d8.zip chromium_src-551acd620a1bc5c48efa05b4119bf90d940279d8.tar.gz chromium_src-551acd620a1bc5c48efa05b4119bf90d940279d8.tar.bz2 |
Unit tests for AudioRendererHost
TEST=AudioRendererHostTest.CreateStream
AudioRendererHostTest.MockStreamDataConversation
BUG=16035
Review URL: http://codereview.chromium.org/150191
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20422 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/renderer_host/audio_renderer_host_unittest.cc | 186 |
1 files changed, 182 insertions, 4 deletions
diff --git a/chrome/browser/renderer_host/audio_renderer_host_unittest.cc b/chrome/browser/renderer_host/audio_renderer_host_unittest.cc index 8efa3e34..5413ced 100644 --- a/chrome/browser/renderer_host/audio_renderer_host_unittest.cc +++ b/chrome/browser/renderer_host/audio_renderer_host_unittest.cc @@ -4,16 +4,121 @@ #include "base/message_loop.h" #include "base/process.h" +#include "base/process_util.h" #include "base/scoped_ptr.h" #include "chrome/browser/renderer_host/audio_renderer_host.h" +#include "chrome/common/render_messages.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Return; +using ::testing::SetArgumentPointee; + +namespace { + +const int kInvalidId = -1; +const int kProcessId = 100; +const int kRouteId = 200; +const int kBufferCapacity = 65536; +const int kPacketSize = 16384; + +} // namespace + +class MockAudioRendererHost : public AudioRendererHost { + public: + MockAudioRendererHost(MessageLoop* loop) + : AudioRendererHost(loop) { + } + + // A list of mock methods. + MOCK_METHOD4(OnRequestPacket, + void(int routing_id, int stream_id, + size_t bytes_in_buffer, int64 message_timestamp)); + + MOCK_METHOD3(OnStreamCreated, + void(int routing_id, int stream_id, int length)); + + MOCK_METHOD4(OnStreamStateChanged, + void(int routing_id, int stream_id, + AudioOutputStream::State state, int info)); + + MOCK_METHOD4(OnStreamVolume, + void(int routing_id, int stream_id, double left, double right)); + + base::SharedMemory* shared_memory() { return shared_memory_.get(); } + + protected: + // This method is used to dispatch IPC messages to the renderer. We intercept + // these messages here and dispatch to our mock methods to verify the + // conversation between this object and the renderer. + virtual void Send(IPC::Message* message) { + CHECK(message); + + // In this method we dispatch the messages to the according handlers as if + // we are the renderer. + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) + IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestPacket) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnStreamCreated) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged, + OnStreamStateChanged) + IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnStreamVolume) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + EXPECT_TRUE(handled); + + delete message; + } + + private: + // These handler methods do minimal things and delegate to the mock methods. + void OnRequestPacket(const IPC::Message& msg, int stream_id, + size_t bytes_in_buffer, int64 message_timestamp) { + OnRequestPacket(msg.routing_id(), stream_id, bytes_in_buffer, + message_timestamp); + } + + void OnStreamCreated(const IPC::Message& msg, int stream_id, + base::SharedMemoryHandle handle, int length) { + // Maps the shared memory. + shared_memory_.reset(new base::SharedMemory(handle, true)); + CHECK(shared_memory_->Map(length)); + CHECK(shared_memory_->memory()); + + // And then delegate the call to the mock method. + OnStreamCreated(msg.routing_id(), stream_id, length); + } + + void OnStreamStateChanged(const IPC::Message& msg, int stream_id, + AudioOutputStream::State state, int info) { + OnStreamStateChanged(msg.routing_id(), stream_id, state, info); + } + + void OnStreamVolume(const IPC::Message& msg, int stream_id, + double left, double right) { + OnStreamVolume(msg.routing_id(), stream_id, left, right); + } + + scoped_ptr<base::SharedMemory> shared_memory_; + + DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); +}; + class AudioRendererHostTest : public testing::Test { + public: + AudioRendererHostTest() + : current_stream_id_(0) { + } + protected: virtual void SetUp() { // Create a message loop so AudioRendererHost can use it. message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); - host_ = new AudioRendererHost(message_loop_.get()); + host_ = new MockAudioRendererHost(message_loop_.get()); + CHECK(host_); } virtual void TearDown() { @@ -24,10 +129,83 @@ class AudioRendererHostTest : public testing::Test { message_loop_->RunAllPending(); } - scoped_refptr<AudioRendererHost> host_; + AudioRendererHost::IPCAudioSource* CreateAudioStream( + AudioManager::Format format) { + InSequence s; + + // 1. We will first receive a OnStreamCreated() signal. + EXPECT_CALL(*host_, + OnStreamCreated(kRouteId, current_stream_id_, kPacketSize)); + + // 2. First packet request will arrive. This request is sent by + // IPCAudioSource::CreateIPCAudioSource to start buffering. + EXPECT_CALL(*host_, OnRequestPacket(kRouteId, current_stream_id_, 0, _)); + + AudioRendererHost::IPCAudioSource* source = + AudioRendererHost::IPCAudioSource::CreateIPCAudioSource( + host_, + kProcessId, + kRouteId, + current_stream_id_, + base::GetCurrentProcessHandle(), + format, + 2, + AudioManager::kAudioCDSampleRate, + 16, + kPacketSize, + kBufferCapacity); + EXPECT_TRUE(source); + EXPECT_EQ(kProcessId, source->process_id()); + EXPECT_EQ(kRouteId, source->route_id()); + EXPECT_EQ(current_stream_id_, source->stream_id()); + return source; + } + + AudioRendererHost::IPCAudioSource* CreateRealStream() { + return CreateAudioStream(AudioManager::AUDIO_PCM_LINEAR); + } + + AudioRendererHost::IPCAudioSource* CreateMockStream() { + return CreateAudioStream(AudioManager::AUDIO_MOCK); + } + + int current_stream_id_; + scoped_refptr<MockAudioRendererHost> host_; scoped_ptr<MessageLoop> message_loop_; + + private: + DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); }; -TEST_F(AudioRendererHostTest, NoTest) { - // TODO(hclam): come up with useful tests. +// Audio output stream only works stably on windows. Also there's no mock +// audio output streams for mac and linux. +// TODO(hclam): make these tests work on mac and linux. +#if defined(OS_WIN) + +TEST_F(AudioRendererHostTest, CreateMockStream) { + scoped_ptr<AudioRendererHost::IPCAudioSource> source(CreateMockStream()); +} + +TEST_F(AudioRendererHostTest, MockStreamDataConversation) { + scoped_ptr<AudioRendererHost::IPCAudioSource> source(CreateMockStream()); + + // We will receive packet requests until the buffer is full. We first send + // three packets of 16KB, then we send packets of 1KB until the buffer is + // full. Then there will no more packet requests. + EXPECT_CALL(*host_, + OnRequestPacket(kRouteId, current_stream_id_, kPacketSize, _)); + EXPECT_CALL(*host_, + OnRequestPacket(kRouteId, current_stream_id_, 2 * kPacketSize, _)); + for (int size = 3 * kPacketSize; size < kBufferCapacity; size += 1024) { + EXPECT_CALL(*host_, OnRequestPacket(kRouteId, current_stream_id_, size, _)); + } + + source->NotifyPacketReady(kPacketSize); + source->NotifyPacketReady(kPacketSize); + source->NotifyPacketReady(kPacketSize); + for (int size = 0; size < kPacketSize; size += 1024) { + source->NotifyPacketReady(1024); + } } + +#endif |