Index: content/renderer/media/audio_device_unittest.cc |
=================================================================== |
--- content/renderer/media/audio_device_unittest.cc (revision 148738) |
+++ content/renderer/media/audio_device_unittest.cc (working copy) |
@@ -1,249 +0,0 @@ |
-// 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 "base/process_util.h" |
-#include "base/shared_memory.h" |
-#include "base/sync_socket.h" |
-#include "base/test/test_timeouts.h" |
-#include "content/common/media/audio_messages.h" |
-#include "content/renderer/media/audio_device.h" |
-#include "content/renderer/media/audio_message_filter.h" |
-#include "media/audio/audio_util.h" |
-#include "media/audio/sample_rates.h" |
-#include "testing/gmock/include/gmock/gmock.h" |
-#include "testing/gmock_mutant.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-using base::CancelableSyncSocket; |
-using base::SharedMemory; |
-using base::SyncSocket; |
-using testing::_; |
-using testing::DoAll; |
-using testing::Invoke; |
-using testing::Return; |
-using testing::WithArgs; |
- |
-namespace { |
- |
-class MockRenderCallback : public media::AudioRendererSink::RenderCallback { |
- public: |
- MockRenderCallback() {} |
- virtual ~MockRenderCallback() {} |
- |
- MOCK_METHOD3(Render, int(const std::vector<float*>& audio_data, |
- int number_of_frames, |
- int audio_delay_milliseconds)); |
- MOCK_METHOD0(OnRenderError, void()); |
-}; |
- |
-class MockAudioMessageFilter : public AudioMessageFilter { |
- public: |
- MockAudioMessageFilter() {} |
- |
- MOCK_METHOD2(CreateStream, |
- void(int stream_id, const media::AudioParameters& params)); |
- MOCK_METHOD1(PlayStream, void(int stream_id)); |
- MOCK_METHOD1(CloseStream, void(int stream_id)); |
- MOCK_METHOD2(SetVolume, void(int stream_id, double volume)); |
- MOCK_METHOD1(PauseStream, void(int stream_id)); |
- MOCK_METHOD1(FlushStream, void(int stream_id)); |
- |
- protected: |
- virtual ~MockAudioMessageFilter() {} |
-}; |
- |
-// Creates a copy of a SyncSocket handle that we can give to AudioDevice. |
-// On Windows this means duplicating the pipe handle so that AudioDevice can |
-// call CloseHandle() (since ownership has been transferred), but on other |
-// platforms, we just copy the same socket handle since AudioDevice on those |
-// platforms won't actually own the socket (FileDescriptor.auto_close is false). |
-bool DuplicateSocketHandle(SyncSocket::Handle socket_handle, |
- SyncSocket::Handle* copy) { |
-#if defined(OS_WIN) |
- HANDLE process = GetCurrentProcess(); |
- ::DuplicateHandle(process, socket_handle, process, copy, |
- 0, FALSE, DUPLICATE_SAME_ACCESS); |
- return *copy != NULL; |
-#else |
- *copy = socket_handle; |
- return *copy != -1; |
-#endif |
-} |
- |
-ACTION_P2(SendPendingBytes, socket, pending_bytes) { |
- socket->Send(&pending_bytes, sizeof(pending_bytes)); |
-} |
- |
-// Used to terminate a loop from a different thread than the loop belongs to. |
-// |loop| should be a MessageLoopProxy. |
-ACTION_P(QuitLoop, loop) { |
- loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
-} |
- |
-// Zeros out |number_of_frames| in all channel buffers pointed to by |
-// the |audio_data| vector. |
-void ZeroAudioData(int number_of_frames, |
- const std::vector<float*>& audio_data) { |
- std::vector<float*>::const_iterator it = audio_data.begin(); |
- for (; it != audio_data.end(); ++it) { |
- float* channel = *it; |
- for (int j = 0; j < number_of_frames; ++j) { |
- channel[j] = 0.0f; |
- } |
- } |
-} |
- |
-} // namespace. |
- |
-class AudioDeviceTest : public testing::Test { |
- public: |
- AudioDeviceTest() |
- : default_audio_parameters_(media::AudioParameters::AUDIO_PCM_LINEAR, |
- CHANNEL_LAYOUT_STEREO, |
- 48000, 16, 1024), |
- stream_id_(-1) { |
- } |
- |
- ~AudioDeviceTest() {} |
- |
- virtual void SetUp() OVERRIDE { |
- // This sets a global audio_message_filter pointer. AudioDevice will pick |
- // up a pointer to this variable via the static AudioMessageFilter::Get() |
- // method. |
- audio_message_filter_ = new MockAudioMessageFilter(); |
- } |
- |
- AudioDevice* CreateAudioDevice() { |
- return new AudioDevice( |
- audio_message_filter_, io_loop_.message_loop_proxy()); |
- } |
- |
- void set_stream_id(int stream_id) { stream_id_ = stream_id; } |
- |
- 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_; |
- const media::AudioParameters default_audio_parameters_; |
- MockRenderCallback callback_; |
- scoped_refptr<MockAudioMessageFilter> audio_message_filter_; |
- int stream_id_; |
-}; |
- |
-// The simplest test for AudioDevice. Used to test construction of AudioDevice |
-// and that the runtime environment is set up correctly. |
-TEST_F(AudioDeviceTest, Initialize) { |
- scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); |
- audio_device->Initialize(default_audio_parameters_, &callback_); |
- io_loop_.RunAllPending(); |
-} |
- |
-// Calls Start() followed by an immediate Stop() and check for the basic message |
-// filter messages being sent in that case. |
-TEST_F(AudioDeviceTest, StartStop) { |
- scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); |
- audio_device->Initialize(default_audio_parameters_, &callback_); |
- |
- audio_device->Start(); |
- audio_device->Stop(); |
- |
- EXPECT_CALL(*audio_message_filter_, CreateStream(_, _)); |
- EXPECT_CALL(*audio_message_filter_, CloseStream(_)); |
- |
- io_loop_.RunAllPending(); |
-} |
- |
-// Starts an audio stream, creates a shared memory section + SyncSocket pair |
-// that AudioDevice must use for audio data. It then sends a request for |
-// a single audio packet and quits when the packet has been sent. |
-TEST_F(AudioDeviceTest, CreateStream) { |
- scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); |
- audio_device->Initialize(default_audio_parameters_, &callback_); |
- |
- audio_device->Start(); |
- |
- EXPECT_CALL(*audio_message_filter_, CreateStream(_, _)) |
- .WillOnce(WithArgs<0>(Invoke(this, &AudioDeviceTest::set_stream_id))); |
- |
- EXPECT_EQ(stream_id_, -1); |
- io_loop_.RunAllPending(); |
- |
- // OnCreateStream() must have been called and we should have a valid |
- // stream id. |
- ASSERT_NE(stream_id_, -1); |
- |
- // This is where it gets a bit hacky. The shared memory contract between |
- // AudioDevice and its browser side counter part includes a bit more than |
- // just the audio data, so we must call TotalSharedMemorySizeInBytes() to get |
- // the actual size needed to fit the audio data plus the extra data. |
- int memory_size = media::TotalSharedMemorySizeInBytes( |
- default_audio_parameters_.GetBytesPerBuffer()); |
- SharedMemory shared_memory; |
- ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size)); |
- memset(shared_memory.memory(), 0xff, memory_size); |
- |
- CancelableSyncSocket browser_socket, renderer_socket; |
- ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket, |
- &renderer_socket)); |
- |
- // Create duplicates of the handles we pass to AudioDevice since ownership |
- // will be transferred and AudioDevice is responsible for freeing. |
- SyncSocket::Handle audio_device_socket = SyncSocket::kInvalidHandle; |
- ASSERT_TRUE(DuplicateSocketHandle(renderer_socket.handle(), |
- &audio_device_socket)); |
- base::SharedMemoryHandle duplicated_memory_handle; |
- ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), |
- &duplicated_memory_handle)); |
- |
- // We should get a 'play' notification when we call OnStreamCreated(). |
- // Respond by asking for some audio data. This should ask our callback |
- // to provide some audio data that AudioDevice then writes into the shared |
- // memory section. |
- EXPECT_CALL(*audio_message_filter_, PlayStream(stream_id_)) |
- .WillOnce(SendPendingBytes(&browser_socket, memory_size)); |
- |
- // We expect calls to our audio renderer callback, which returns the number |
- // of frames written to the memory section. |
- // Here's the second place where it gets hacky: There's no way for us to |
- // know (without using a sleep loop!) when the AudioDevice has finished |
- // writing the interleaved audio data into the shared memory section. |
- // So, for the sake of this test, we consider the call to Render a sign |
- // of success and quit the loop. |
- |
- // A note on the call to ZeroAudioData(): |
- // Valgrind caught a bug in AudioDevice::AudioThreadCallback::Process() |
- // whereby we always interleaved all the frames in the buffer regardless |
- // of how many were actually rendered. So to keep the benefits of that |
- // test, we explicitly pass 0 in here as the number of frames to |
- // ZeroAudioData(). Other tests might want to pass the requested number |
- // by using WithArgs<1, 0>(Invoke(&ZeroAudioData)) and set the return |
- // value accordingly. |
- const int kNumberOfFramesToProcess = 0; |
- |
- EXPECT_CALL(callback_, Render(_, _, _)) |
- .WillOnce(DoAll( |
- WithArgs<0>(Invoke( |
- testing::CreateFunctor(&ZeroAudioData, |
- kNumberOfFramesToProcess))), |
- QuitLoop(io_loop_.message_loop_proxy()), |
- Return(kNumberOfFramesToProcess))); |
- |
- audio_device->OnStreamCreated(duplicated_memory_handle, audio_device_socket, |
- memory_size); |
- |
- io_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
- TestTimeouts::action_timeout()); |
- io_loop_.Run(); |
- |
- // Close the stream sequence. |
- EXPECT_CALL(*audio_message_filter_, CloseStream(stream_id_)); |
- |
- audio_device->Stop(); |
- io_loop_.RunAllPending(); |
-} |