| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #include "base/at_exit.h" | 7 #include "base/at_exit.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/process_util.h" | 9 #include "base/process_util.h" |
| 10 #include "base/shared_memory.h" | 10 #include "base/shared_memory.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 using base::SharedMemory; | 23 using base::SharedMemory; |
| 24 using base::SyncSocket; | 24 using base::SyncSocket; |
| 25 using testing::_; | 25 using testing::_; |
| 26 using testing::DoAll; | 26 using testing::DoAll; |
| 27 using testing::Invoke; | 27 using testing::Invoke; |
| 28 using testing::Return; | 28 using testing::Return; |
| 29 using testing::WithArgs; | 29 using testing::WithArgs; |
| 30 | 30 |
| 31 namespace { | 31 namespace { |
| 32 | 32 |
| 33 // Derived from AudioDevice to gain access to the protected constructor. | |
| 34 class TestAudioDevice : public AudioDevice { | |
| 35 public: | |
| 36 explicit TestAudioDevice(const scoped_refptr<base::MessageLoopProxy>& io_loop) | |
| 37 : AudioDevice(io_loop) {} | |
| 38 | |
| 39 protected: | |
| 40 virtual ~TestAudioDevice() {} | |
| 41 }; | |
| 42 | |
| 43 class MockRenderCallback : public media::AudioRendererSink::RenderCallback { | 33 class MockRenderCallback : public media::AudioRendererSink::RenderCallback { |
| 44 public: | 34 public: |
| 45 MockRenderCallback() {} | 35 MockRenderCallback() {} |
| 46 virtual ~MockRenderCallback() {} | 36 virtual ~MockRenderCallback() {} |
| 47 | 37 |
| 48 MOCK_METHOD3(Render, int(const std::vector<float*>& audio_data, | 38 MOCK_METHOD3(Render, int(const std::vector<float*>& audio_data, |
| 49 int number_of_frames, | 39 int number_of_frames, |
| 50 int audio_delay_milliseconds)); | 40 int audio_delay_milliseconds)); |
| 51 MOCK_METHOD0(OnRenderError, void()); | 41 MOCK_METHOD0(OnRenderError, void()); |
| 52 }; | 42 }; |
| 53 | 43 |
| 54 class MockAudioMessageFilter : public AudioMessageFilter { | 44 class MockAudioMessageFilter : public AudioMessageFilter { |
| 55 public: | 45 public: |
| 56 MockAudioMessageFilter() {} | 46 MockAudioMessageFilter() {} |
| 57 | 47 |
| 58 virtual bool Send(IPC::Message* message) OVERRIDE { | 48 MOCK_METHOD2(CreateStream, |
| 59 bool handled = true; | |
| 60 IPC_BEGIN_MESSAGE_MAP(MockAudioMessageFilter, *message) | |
| 61 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) | |
| 62 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) | |
| 63 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) | |
| 64 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) | |
| 65 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) | |
| 66 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) | |
| 67 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 68 IPC_END_MESSAGE_MAP() | |
| 69 EXPECT_TRUE(handled); | |
| 70 delete message; | |
| 71 return true; | |
| 72 } | |
| 73 | |
| 74 MOCK_METHOD2(OnCreateStream, | |
| 75 void(int stream_id, const media::AudioParameters& params)); | 49 void(int stream_id, const media::AudioParameters& params)); |
| 76 MOCK_METHOD1(OnPlayStream, void(int stream_id)); | 50 MOCK_METHOD1(PlayStream, void(int stream_id)); |
| 77 MOCK_METHOD1(OnCloseStream, void(int stream_id)); | 51 MOCK_METHOD1(CloseStream, void(int stream_id)); |
| 78 MOCK_METHOD2(OnSetVolume, void(int stream_id, double volume)); | 52 MOCK_METHOD2(SetVolume, void(int stream_id, double volume)); |
| 79 MOCK_METHOD1(OnPauseStream, void(int stream_id)); | 53 MOCK_METHOD1(PauseStream, void(int stream_id)); |
| 80 MOCK_METHOD1(OnFlushStream, void(int stream_id)); | 54 MOCK_METHOD1(FlushStream, void(int stream_id)); |
| 81 | 55 |
| 82 protected: | 56 protected: |
| 83 virtual ~MockAudioMessageFilter() {} | 57 virtual ~MockAudioMessageFilter() {} |
| 84 }; | 58 }; |
| 85 | 59 |
| 86 // Creates a copy of a SyncSocket handle that we can give to AudioDevice. | 60 // Creates a copy of a SyncSocket handle that we can give to AudioDevice. |
| 87 // On Windows this means duplicating the pipe handle so that AudioDevice can | 61 // On Windows this means duplicating the pipe handle so that AudioDevice can |
| 88 // call CloseHandle() (since ownership has been transferred), but on other | 62 // call CloseHandle() (since ownership has been transferred), but on other |
| 89 // platforms, we just copy the same socket handle since AudioDevice on those | 63 // platforms, we just copy the same socket handle since AudioDevice on those |
| 90 // platforms won't actually own the socket (FileDescriptor.auto_close is false). | 64 // platforms won't actually own the socket (FileDescriptor.auto_close is false). |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 ~AudioDeviceTest() {} | 112 ~AudioDeviceTest() {} |
| 139 | 113 |
| 140 virtual void SetUp() OVERRIDE { | 114 virtual void SetUp() OVERRIDE { |
| 141 // This sets a global audio_message_filter pointer. AudioDevice will pick | 115 // This sets a global audio_message_filter pointer. AudioDevice will pick |
| 142 // up a pointer to this variable via the static AudioMessageFilter::Get() | 116 // up a pointer to this variable via the static AudioMessageFilter::Get() |
| 143 // method. | 117 // method. |
| 144 audio_message_filter_ = new MockAudioMessageFilter(); | 118 audio_message_filter_ = new MockAudioMessageFilter(); |
| 145 } | 119 } |
| 146 | 120 |
| 147 AudioDevice* CreateAudioDevice() { | 121 AudioDevice* CreateAudioDevice() { |
| 148 return new TestAudioDevice(io_loop_.message_loop_proxy()); | 122 return new AudioDevice( |
| 123 audio_message_filter_, io_loop_.message_loop_proxy()); |
| 149 } | 124 } |
| 150 | 125 |
| 151 void set_stream_id(int stream_id) { stream_id_ = stream_id; } | 126 void set_stream_id(int stream_id) { stream_id_ = stream_id; } |
| 152 | 127 |
| 153 protected: | 128 protected: |
| 154 // Used to clean up TLS pointers that the test(s) will initialize. | 129 // Used to clean up TLS pointers that the test(s) will initialize. |
| 155 // Must remain the first member of this class. | 130 // Must remain the first member of this class. |
| 156 base::ShadowingAtExitManager at_exit_manager_; | 131 base::ShadowingAtExitManager at_exit_manager_; |
| 157 MessageLoopForIO io_loop_; | 132 MessageLoopForIO io_loop_; |
| 158 const media::AudioParameters default_audio_parameters_; | 133 const media::AudioParameters default_audio_parameters_; |
| 159 MockRenderCallback callback_; | 134 MockRenderCallback callback_; |
| 160 scoped_refptr<MockAudioMessageFilter> audio_message_filter_; | 135 scoped_refptr<MockAudioMessageFilter> audio_message_filter_; |
| 161 int stream_id_; | 136 int stream_id_; |
| 162 }; | 137 }; |
| 163 | 138 |
| 164 // The simplest test for AudioDevice. Used to test construction of AudioDevice | 139 // The simplest test for AudioDevice. Used to test construction of AudioDevice |
| 165 // and that the runtime environment is set up correctly (e.g. ChildProcess and | 140 // and that the runtime environment is set up correctly. |
| 166 // AudioMessageFilter global pointers). | |
| 167 TEST_F(AudioDeviceTest, Initialize) { | 141 TEST_F(AudioDeviceTest, Initialize) { |
| 168 scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); | 142 scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); |
| 169 audio_device->Initialize(default_audio_parameters_, &callback_); | 143 audio_device->Initialize(default_audio_parameters_, &callback_); |
| 170 io_loop_.RunAllPending(); | 144 io_loop_.RunAllPending(); |
| 171 } | 145 } |
| 172 | 146 |
| 173 // Calls Start() followed by an immediate Stop() and check for the basic message | 147 // Calls Start() followed by an immediate Stop() and check for the basic message |
| 174 // filter messages being sent in that case. | 148 // filter messages being sent in that case. |
| 175 TEST_F(AudioDeviceTest, StartStop) { | 149 TEST_F(AudioDeviceTest, StartStop) { |
| 176 scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); | 150 scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); |
| 177 audio_device->Initialize(default_audio_parameters_, &callback_); | 151 audio_device->Initialize(default_audio_parameters_, &callback_); |
| 178 | 152 |
| 179 audio_device->Start(); | 153 audio_device->Start(); |
| 180 audio_device->Stop(); | 154 audio_device->Stop(); |
| 181 | 155 |
| 182 EXPECT_CALL(*audio_message_filter_, OnCreateStream(_, _)); | 156 EXPECT_CALL(*audio_message_filter_, CreateStream(_, _)); |
| 183 EXPECT_CALL(*audio_message_filter_, OnCloseStream(_)); | 157 EXPECT_CALL(*audio_message_filter_, CloseStream(_)); |
| 184 | 158 |
| 185 io_loop_.RunAllPending(); | 159 io_loop_.RunAllPending(); |
| 186 } | 160 } |
| 187 | 161 |
| 188 // Starts an audio stream, creates a shared memory section + SyncSocket pair | 162 // Starts an audio stream, creates a shared memory section + SyncSocket pair |
| 189 // that AudioDevice must use for audio data. It then sends a request for | 163 // that AudioDevice must use for audio data. It then sends a request for |
| 190 // a single audio packet and quits when the packet has been sent. | 164 // a single audio packet and quits when the packet has been sent. |
| 191 TEST_F(AudioDeviceTest, CreateStream) { | 165 TEST_F(AudioDeviceTest, CreateStream) { |
| 192 scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); | 166 scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); |
| 193 audio_device->Initialize(default_audio_parameters_, &callback_); | 167 audio_device->Initialize(default_audio_parameters_, &callback_); |
| 194 | 168 |
| 195 audio_device->Start(); | 169 audio_device->Start(); |
| 196 | 170 |
| 197 EXPECT_CALL(*audio_message_filter_, OnCreateStream(_, _)) | 171 EXPECT_CALL(*audio_message_filter_, CreateStream(_, _)) |
| 198 .WillOnce(WithArgs<0>(Invoke(this, &AudioDeviceTest::set_stream_id))); | 172 .WillOnce(WithArgs<0>(Invoke(this, &AudioDeviceTest::set_stream_id))); |
| 199 | 173 |
| 200 EXPECT_EQ(stream_id_, -1); | 174 EXPECT_EQ(stream_id_, -1); |
| 201 io_loop_.RunAllPending(); | 175 io_loop_.RunAllPending(); |
| 176 |
| 202 // OnCreateStream() must have been called and we should have a valid | 177 // OnCreateStream() must have been called and we should have a valid |
| 203 // stream id. | 178 // stream id. |
| 204 ASSERT_NE(stream_id_, -1); | 179 ASSERT_NE(stream_id_, -1); |
| 205 | 180 |
| 206 // This is where it gets a bit hacky. The shared memory contract between | 181 // This is where it gets a bit hacky. The shared memory contract between |
| 207 // AudioDevice and its browser side counter part includes a bit more than | 182 // AudioDevice and its browser side counter part includes a bit more than |
| 208 // just the audio data, so we must call TotalSharedMemorySizeInBytes() to get | 183 // just the audio data, so we must call TotalSharedMemorySizeInBytes() to get |
| 209 // the actual size needed to fit the audio data plus the extra data. | 184 // the actual size needed to fit the audio data plus the extra data. |
| 210 int memory_size = media::TotalSharedMemorySizeInBytes( | 185 int memory_size = media::TotalSharedMemorySizeInBytes( |
| 211 default_audio_parameters_.GetBytesPerBuffer()); | 186 default_audio_parameters_.GetBytesPerBuffer()); |
| 212 SharedMemory shared_memory; | 187 SharedMemory shared_memory; |
| 213 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size)); | 188 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size)); |
| 214 // Initialize the memory. | |
| 215 memset(shared_memory.memory(), 0xff, memory_size); | 189 memset(shared_memory.memory(), 0xff, memory_size); |
| 216 | 190 |
| 217 CancelableSyncSocket browser_socket, renderer_socket; | 191 CancelableSyncSocket browser_socket, renderer_socket; |
| 218 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket, | 192 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket, |
| 219 &renderer_socket)); | 193 &renderer_socket)); |
| 220 | 194 |
| 221 // Create duplicates of the handles we pass to AudioDevice since ownership | 195 // Create duplicates of the handles we pass to AudioDevice since ownership |
| 222 // will be transferred and AudioDevice is responsible for freeing. | 196 // will be transferred and AudioDevice is responsible for freeing. |
| 223 SyncSocket::Handle audio_device_socket = SyncSocket::kInvalidHandle; | 197 SyncSocket::Handle audio_device_socket = SyncSocket::kInvalidHandle; |
| 224 ASSERT_TRUE(DuplicateSocketHandle(renderer_socket.handle(), | 198 ASSERT_TRUE(DuplicateSocketHandle(renderer_socket.handle(), |
| 225 &audio_device_socket)); | 199 &audio_device_socket)); |
| 226 base::SharedMemoryHandle duplicated_memory_handle; | 200 base::SharedMemoryHandle duplicated_memory_handle; |
| 227 ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), | 201 ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), |
| 228 &duplicated_memory_handle)); | 202 &duplicated_memory_handle)); |
| 229 | 203 |
| 230 // We should get a 'play' notification when we call OnStreamCreated(). | 204 // We should get a 'play' notification when we call OnStreamCreated(). |
| 231 // Respond by asking for some audio data. This should ask our callback | 205 // Respond by asking for some audio data. This should ask our callback |
| 232 // to provide some audio data that AudioDevice then writes into the shared | 206 // to provide some audio data that AudioDevice then writes into the shared |
| 233 // memory section. | 207 // memory section. |
| 234 EXPECT_CALL(*audio_message_filter_, OnPlayStream(stream_id_)) | 208 EXPECT_CALL(*audio_message_filter_, PlayStream(stream_id_)) |
| 235 .WillOnce(SendPendingBytes(&browser_socket, memory_size)); | 209 .WillOnce(SendPendingBytes(&browser_socket, memory_size)); |
| 236 | 210 |
| 237 // We expect calls to our audio renderer callback, which returns the number | 211 // We expect calls to our audio renderer callback, which returns the number |
| 238 // of frames written to the memory section. | 212 // of frames written to the memory section. |
| 239 // Here's the second place where it gets hacky: There's no way for us to | 213 // Here's the second place where it gets hacky: There's no way for us to |
| 240 // know (without using a sleep loop!) when the AudioDevice has finished | 214 // know (without using a sleep loop!) when the AudioDevice has finished |
| 241 // writing the interleaved audio data into the shared memory section. | 215 // writing the interleaved audio data into the shared memory section. |
| 242 // So, for the sake of this test, we consider the call to Render a sign | 216 // So, for the sake of this test, we consider the call to Render a sign |
| 243 // of success and quit the loop. | 217 // of success and quit the loop. |
| 244 | 218 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 261 Return(kNumberOfFramesToProcess))); | 235 Return(kNumberOfFramesToProcess))); |
| 262 | 236 |
| 263 audio_device->OnStreamCreated(duplicated_memory_handle, audio_device_socket, | 237 audio_device->OnStreamCreated(duplicated_memory_handle, audio_device_socket, |
| 264 memory_size); | 238 memory_size); |
| 265 | 239 |
| 266 io_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 240 io_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
| 267 TestTimeouts::action_timeout()); | 241 TestTimeouts::action_timeout()); |
| 268 io_loop_.Run(); | 242 io_loop_.Run(); |
| 269 | 243 |
| 270 // Close the stream sequence. | 244 // Close the stream sequence. |
| 271 | 245 EXPECT_CALL(*audio_message_filter_, CloseStream(stream_id_)); |
| 272 EXPECT_CALL(*audio_message_filter_, OnCloseStream(stream_id_)); | |
| 273 | 246 |
| 274 audio_device->Stop(); | 247 audio_device->Stop(); |
| 275 io_loop_.RunAllPending(); | 248 io_loop_.RunAllPending(); |
| 276 } | 249 } |
| OLD | NEW |