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 |