OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/environment.h" | 5 #include "base/environment.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/process_util.h" | 8 #include "base/process_util.h" |
9 #include "base/sync_socket.h" | 9 #include "base/sync_socket.h" |
10 #include "content/browser/browser_thread.h" | 10 #include "content/browser/browser_thread.h" |
11 #include "content/browser/renderer_host/media/audio_renderer_host.h" | 11 #include "content/browser/renderer_host/media/audio_renderer_host.h" |
12 #include "content/common/media/audio_messages.h" | 12 #include "content/common/media/audio_messages.h" |
13 #include "ipc/ipc_message_utils.h" | 13 #include "ipc/ipc_message_utils.h" |
14 #include "media/audio/audio_manager.h" | 14 #include "media/audio/audio_manager.h" |
15 #include "media/audio/fake_audio_output_stream.h" | 15 #include "media/audio/fake_audio_output_stream.h" |
16 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
18 | 18 |
19 using ::testing::_; | 19 using ::testing::_; |
20 using ::testing::DoAll; | 20 using ::testing::DoAll; |
21 using ::testing::InSequence; | 21 using ::testing::InSequence; |
22 using ::testing::InvokeWithoutArgs; | 22 using ::testing::InvokeWithoutArgs; |
23 using ::testing::Return; | 23 using ::testing::Return; |
24 using ::testing::SaveArg; | 24 using ::testing::SaveArg; |
25 using ::testing::SetArgumentPointee; | 25 using ::testing::SetArgumentPointee; |
26 | 26 |
27 static const int kInvalidId = -1; | |
28 static const int kRouteId = 200; | |
29 static const int kStreamId = 50; | 27 static const int kStreamId = 50; |
30 | 28 |
31 static bool IsRunningHeadless() { | 29 static bool IsRunningHeadless() { |
32 scoped_ptr<base::Environment> env(base::Environment::Create()); | 30 scoped_ptr<base::Environment> env(base::Environment::Create()); |
33 if (env->HasVar("CHROME_HEADLESS")) | 31 if (env->HasVar("CHROME_HEADLESS")) |
34 return true; | 32 return true; |
35 return false; | 33 return false; |
36 } | 34 } |
37 | 35 |
38 class MockAudioRendererHost : public AudioRendererHost { | 36 class MockAudioRendererHost : public AudioRendererHost { |
39 public: | 37 public: |
40 MockAudioRendererHost() : shared_memory_length_(0) { | 38 MockAudioRendererHost() : shared_memory_length_(0) { |
41 } | 39 } |
42 | 40 |
43 virtual ~MockAudioRendererHost() { | 41 virtual ~MockAudioRendererHost() { |
44 } | 42 } |
45 | 43 |
46 // A list of mock methods. | 44 // A list of mock methods. |
47 MOCK_METHOD3(OnRequestPacket, | 45 MOCK_METHOD2(OnRequestPacket, |
48 void(int routing_id, int stream_id, | 46 void(int stream_id, AudioBuffersState buffers_state)); |
49 AudioBuffersState buffers_state)); | 47 MOCK_METHOD2(OnStreamCreated, |
50 MOCK_METHOD3(OnStreamCreated, | 48 void(int stream_id, int length)); |
51 void(int routing_id, int stream_id, int length)); | 49 MOCK_METHOD2(OnLowLatencyStreamCreated, |
52 MOCK_METHOD3(OnLowLatencyStreamCreated, | 50 void(int stream_id, int length)); |
53 void(int routing_id, int stream_id, int length)); | 51 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); |
54 MOCK_METHOD2(OnStreamPlaying, void(int routing_id, int stream_id)); | 52 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); |
55 MOCK_METHOD2(OnStreamPaused, void(int routing_id, int stream_id)); | 53 MOCK_METHOD1(OnStreamError, void(int stream_id)); |
56 MOCK_METHOD2(OnStreamError, void(int routing_id, int stream_id)); | 54 MOCK_METHOD2(OnStreamVolume, |
57 MOCK_METHOD3(OnStreamVolume, | 55 void(int stream_id, double volume)); |
58 void(int routing_id, int stream_id, double volume)); | |
59 | 56 |
60 base::SharedMemory* shared_memory() { return shared_memory_.get(); } | 57 base::SharedMemory* shared_memory() { return shared_memory_.get(); } |
61 uint32 shared_memory_length() { return shared_memory_length_; } | 58 uint32 shared_memory_length() { return shared_memory_length_; } |
62 | 59 |
63 base::SyncSocket* sync_socket() { return sync_socket_.get(); } | 60 base::SyncSocket* sync_socket() { return sync_socket_.get(); } |
64 | 61 |
65 private: | 62 private: |
66 // This method is used to dispatch IPC messages to the renderer. We intercept | 63 // This method is used to dispatch IPC messages to the renderer. We intercept |
67 // these messages here and dispatch to our mock methods to verify the | 64 // these messages here and dispatch to our mock methods to verify the |
68 // conversation between this object and the renderer. | 65 // conversation between this object and the renderer. |
(...skipping 15 matching lines...) Expand all Loading... |
84 IPC_END_MESSAGE_MAP() | 81 IPC_END_MESSAGE_MAP() |
85 EXPECT_TRUE(handled); | 82 EXPECT_TRUE(handled); |
86 | 83 |
87 delete message; | 84 delete message; |
88 return true; | 85 return true; |
89 } | 86 } |
90 | 87 |
91 // These handler methods do minimal things and delegate to the mock methods. | 88 // These handler methods do minimal things and delegate to the mock methods. |
92 void OnRequestPacket(const IPC::Message& msg, int stream_id, | 89 void OnRequestPacket(const IPC::Message& msg, int stream_id, |
93 AudioBuffersState buffers_state) { | 90 AudioBuffersState buffers_state) { |
94 OnRequestPacket(msg.routing_id(), stream_id, buffers_state); | 91 OnRequestPacket(stream_id, buffers_state); |
95 } | 92 } |
96 | 93 |
97 void OnStreamCreated(const IPC::Message& msg, int stream_id, | 94 void OnStreamCreated(const IPC::Message& msg, int stream_id, |
98 base::SharedMemoryHandle handle, uint32 length) { | 95 base::SharedMemoryHandle handle, uint32 length) { |
99 // Maps the shared memory. | 96 // Maps the shared memory. |
100 shared_memory_.reset(new base::SharedMemory(handle, false)); | 97 shared_memory_.reset(new base::SharedMemory(handle, false)); |
101 ASSERT_TRUE(shared_memory_->Map(length)); | 98 ASSERT_TRUE(shared_memory_->Map(length)); |
102 ASSERT_TRUE(shared_memory_->memory()); | 99 ASSERT_TRUE(shared_memory_->memory()); |
103 shared_memory_length_ = length; | 100 shared_memory_length_ = length; |
104 | 101 |
105 // And then delegate the call to the mock method. | 102 // And then delegate the call to the mock method. |
106 OnStreamCreated(msg.routing_id(), stream_id, length); | 103 OnStreamCreated(stream_id, length); |
107 } | 104 } |
108 | 105 |
109 void OnLowLatencyStreamCreated(const IPC::Message& msg, int stream_id, | 106 void OnLowLatencyStreamCreated(const IPC::Message& msg, int stream_id, |
110 base::SharedMemoryHandle handle, | 107 base::SharedMemoryHandle handle, |
111 #if defined(OS_WIN) | 108 #if defined(OS_WIN) |
112 base::SyncSocket::Handle socket_handle, | 109 base::SyncSocket::Handle socket_handle, |
113 #else | 110 #else |
114 base::FileDescriptor socket_descriptor, | 111 base::FileDescriptor socket_descriptor, |
115 #endif | 112 #endif |
116 uint32 length) { | 113 uint32 length) { |
117 // Maps the shared memory. | 114 // Maps the shared memory. |
118 shared_memory_.reset(new base::SharedMemory(handle, false)); | 115 shared_memory_.reset(new base::SharedMemory(handle, false)); |
119 CHECK(shared_memory_->Map(length)); | 116 CHECK(shared_memory_->Map(length)); |
120 CHECK(shared_memory_->memory()); | 117 CHECK(shared_memory_->memory()); |
121 shared_memory_length_ = length; | 118 shared_memory_length_ = length; |
122 | 119 |
123 // Create the SyncSocket using the handle. | 120 // Create the SyncSocket using the handle. |
124 base::SyncSocket::Handle sync_socket_handle; | 121 base::SyncSocket::Handle sync_socket_handle; |
125 #if defined(OS_WIN) | 122 #if defined(OS_WIN) |
126 sync_socket_handle = socket_handle; | 123 sync_socket_handle = socket_handle; |
127 #else | 124 #else |
128 sync_socket_handle = socket_descriptor.fd; | 125 sync_socket_handle = socket_descriptor.fd; |
129 #endif | 126 #endif |
130 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); | 127 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); |
131 | 128 |
132 // And then delegate the call to the mock method. | 129 // And then delegate the call to the mock method. |
133 OnLowLatencyStreamCreated(msg.routing_id(), stream_id, length); | 130 OnLowLatencyStreamCreated(stream_id, length); |
134 } | 131 } |
135 | 132 |
136 void OnStreamStateChanged(const IPC::Message& msg, int stream_id, | 133 void OnStreamStateChanged(const IPC::Message& msg, int stream_id, |
137 AudioStreamState state) { | 134 AudioStreamState state) { |
138 if (state == kAudioStreamPlaying) { | 135 if (state == kAudioStreamPlaying) { |
139 OnStreamPlaying(msg.routing_id(), stream_id); | 136 OnStreamPlaying(stream_id); |
140 } else if (state == kAudioStreamPaused) { | 137 } else if (state == kAudioStreamPaused) { |
141 OnStreamPaused(msg.routing_id(), stream_id); | 138 OnStreamPaused(stream_id); |
142 } else if (state == kAudioStreamError) { | 139 } else if (state == kAudioStreamError) { |
143 OnStreamError(msg.routing_id(), stream_id); | 140 OnStreamError(stream_id); |
144 } else { | 141 } else { |
145 FAIL() << "Unknown stream state"; | 142 FAIL() << "Unknown stream state"; |
146 } | 143 } |
147 } | 144 } |
148 | 145 |
149 void OnStreamVolume(const IPC::Message& msg, int stream_id, double volume) { | 146 void OnStreamVolume(const IPC::Message& msg, int stream_id, double volume) { |
150 OnStreamVolume(msg.routing_id(), stream_id, volume); | 147 OnStreamVolume(stream_id, volume); |
151 } | 148 } |
152 | 149 |
153 scoped_ptr<base::SharedMemory> shared_memory_; | 150 scoped_ptr<base::SharedMemory> shared_memory_; |
154 scoped_ptr<base::SyncSocket> sync_socket_; | 151 scoped_ptr<base::SyncSocket> sync_socket_; |
155 uint32 shared_memory_length_; | 152 uint32 shared_memory_length_; |
156 | 153 |
157 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); | 154 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); |
158 }; | 155 }; |
159 | 156 |
160 ACTION_P(QuitMessageLoop, message_loop) { | 157 ACTION_P(QuitMessageLoop, message_loop) { |
(...skipping 28 matching lines...) Expand all Loading... |
189 // We need to continue running message_loop_ to complete all destructions. | 186 // We need to continue running message_loop_ to complete all destructions. |
190 SyncWithAudioThread(); | 187 SyncWithAudioThread(); |
191 | 188 |
192 io_thread_.reset(); | 189 io_thread_.reset(); |
193 } | 190 } |
194 | 191 |
195 void Create() { | 192 void Create() { |
196 InSequence s; | 193 InSequence s; |
197 // 1. We will first receive a OnStreamCreated() signal. | 194 // 1. We will first receive a OnStreamCreated() signal. |
198 EXPECT_CALL(*host_, | 195 EXPECT_CALL(*host_, |
199 OnStreamCreated(kRouteId, kStreamId, _)); | 196 OnStreamCreated(kStreamId, _)); |
200 | 197 |
201 // 2. First packet request will arrive. | 198 // 2. First packet request will arrive. |
202 EXPECT_CALL(*host_, OnRequestPacket(kRouteId, kStreamId, _)) | 199 EXPECT_CALL(*host_, OnRequestPacket(kStreamId, _)) |
203 .WillOnce(QuitMessageLoop(message_loop_.get())); | 200 .WillOnce(QuitMessageLoop(message_loop_.get())); |
204 | 201 |
205 IPC::Message msg; | |
206 msg.set_routing_id(kRouteId); | |
207 | |
208 AudioParameters params; | 202 AudioParameters params; |
209 if (mock_stream_) | 203 if (mock_stream_) |
210 params.format = AudioParameters::AUDIO_MOCK; | 204 params.format = AudioParameters::AUDIO_MOCK; |
211 else | 205 else |
212 params.format = AudioParameters::AUDIO_PCM_LINEAR; | 206 params.format = AudioParameters::AUDIO_PCM_LINEAR; |
213 params.channels = 2; | 207 params.channels = 2; |
214 params.sample_rate = AudioParameters::kAudioCDSampleRate; | 208 params.sample_rate = AudioParameters::kAudioCDSampleRate; |
215 params.bits_per_sample = 16; | 209 params.bits_per_sample = 16; |
216 params.samples_per_packet = 0; | 210 params.samples_per_packet = 0; |
217 | 211 |
218 // Send a create stream message to the audio output stream and wait until | 212 // Send a create stream message to the audio output stream and wait until |
219 // we receive the created message. | 213 // we receive the created message. |
220 host_->OnCreateStream(msg, kStreamId, params, false); | 214 host_->OnCreateStream(kStreamId, params, false); |
221 message_loop_->Run(); | 215 message_loop_->Run(); |
222 } | 216 } |
223 | 217 |
224 void CreateLowLatency() { | 218 void CreateLowLatency() { |
225 InSequence s; | 219 InSequence s; |
226 // We will first receive a OnLowLatencyStreamCreated() signal. | 220 // We will first receive a OnLowLatencyStreamCreated() signal. |
227 EXPECT_CALL(*host_, | 221 EXPECT_CALL(*host_, |
228 OnLowLatencyStreamCreated(kRouteId, kStreamId, _)) | 222 OnLowLatencyStreamCreated(kStreamId, _)) |
229 .WillOnce(QuitMessageLoop(message_loop_.get())); | 223 .WillOnce(QuitMessageLoop(message_loop_.get())); |
230 | 224 |
231 IPC::Message msg; | |
232 msg.set_routing_id(kRouteId); | |
233 | |
234 AudioParameters params; | 225 AudioParameters params; |
235 if (mock_stream_) | 226 if (mock_stream_) |
236 params.format = AudioParameters::AUDIO_MOCK; | 227 params.format = AudioParameters::AUDIO_MOCK; |
237 else | 228 else |
238 params.format = AudioParameters::AUDIO_PCM_LINEAR; | 229 params.format = AudioParameters::AUDIO_PCM_LINEAR; |
239 params.channels = 2; | 230 params.channels = 2; |
240 params.sample_rate = AudioParameters::kAudioCDSampleRate; | 231 params.sample_rate = AudioParameters::kAudioCDSampleRate; |
241 params.bits_per_sample = 16; | 232 params.bits_per_sample = 16; |
242 params.samples_per_packet = 0; | 233 params.samples_per_packet = 0; |
243 | 234 |
244 // Send a create stream message to the audio output stream and wait until | 235 // Send a create stream message to the audio output stream and wait until |
245 // we receive the created message. | 236 // we receive the created message. |
246 host_->OnCreateStream(msg, kStreamId, params, true); | 237 host_->OnCreateStream(kStreamId, params, true); |
247 message_loop_->Run(); | 238 message_loop_->Run(); |
248 } | 239 } |
249 | 240 |
250 void Close() { | 241 void Close() { |
251 // Send a message to AudioRendererHost to tell it we want to close the | 242 // Send a message to AudioRendererHost to tell it we want to close the |
252 // stream. | 243 // stream. |
253 IPC::Message msg; | 244 host_->OnCloseStream(kStreamId); |
254 msg.set_routing_id(kRouteId); | |
255 host_->OnCloseStream(msg, kStreamId); | |
256 message_loop_->RunAllPending(); | 245 message_loop_->RunAllPending(); |
257 } | 246 } |
258 | 247 |
259 void Play() { | 248 void Play() { |
260 EXPECT_CALL(*host_, OnStreamPlaying(kRouteId, kStreamId)) | 249 EXPECT_CALL(*host_, OnStreamPlaying(kStreamId)) |
261 .WillOnce(QuitMessageLoop(message_loop_.get())); | 250 .WillOnce(QuitMessageLoop(message_loop_.get())); |
262 | 251 |
263 IPC::Message msg; | 252 host_->OnPlayStream(kStreamId); |
264 msg.set_routing_id(kRouteId); | |
265 host_->OnPlayStream(msg, kStreamId); | |
266 message_loop_->Run(); | 253 message_loop_->Run(); |
267 } | 254 } |
268 | 255 |
269 void Pause() { | 256 void Pause() { |
270 EXPECT_CALL(*host_, OnStreamPaused(kRouteId, kStreamId)) | 257 EXPECT_CALL(*host_, OnStreamPaused(kStreamId)) |
271 .WillOnce(QuitMessageLoop(message_loop_.get())); | 258 .WillOnce(QuitMessageLoop(message_loop_.get())); |
272 | 259 |
273 IPC::Message msg; | 260 host_->OnPauseStream(kStreamId); |
274 msg.set_routing_id(kRouteId); | |
275 host_->OnPauseStream(msg, kStreamId); | |
276 message_loop_->Run(); | 261 message_loop_->Run(); |
277 } | 262 } |
278 | 263 |
279 void SetVolume(double volume) { | 264 void SetVolume(double volume) { |
280 IPC::Message msg; | 265 host_->OnSetVolume(kStreamId, volume); |
281 msg.set_routing_id(kRouteId); | |
282 host_->OnSetVolume(msg, kStreamId, volume); | |
283 message_loop_->RunAllPending(); | 266 message_loop_->RunAllPending(); |
284 } | 267 } |
285 | 268 |
286 void NotifyPacketReady() { | 269 void NotifyPacketReady() { |
287 EXPECT_CALL(*host_, OnRequestPacket(kRouteId, kStreamId, _)) | 270 EXPECT_CALL(*host_, OnRequestPacket(kStreamId, _)) |
288 .WillOnce(QuitMessageLoop(message_loop_.get())); | 271 .WillOnce(QuitMessageLoop(message_loop_.get())); |
289 | 272 |
290 IPC::Message msg; | |
291 msg.set_routing_id(kRouteId); | |
292 memset(host_->shared_memory()->memory(), 0, host_->shared_memory_length()); | 273 memset(host_->shared_memory()->memory(), 0, host_->shared_memory_length()); |
293 host_->OnNotifyPacketReady(msg, kStreamId, | 274 host_->OnNotifyPacketReady(kStreamId, host_->shared_memory_length()); |
294 host_->shared_memory_length()); | |
295 message_loop_->Run(); | 275 message_loop_->Run(); |
296 } | 276 } |
297 | 277 |
298 void SimulateError() { | 278 void SimulateError() { |
299 // Find the first AudioOutputController in the AudioRendererHost. | 279 // Find the first AudioOutputController in the AudioRendererHost. |
300 CHECK(host_->audio_entries_.size()) | 280 CHECK(host_->audio_entries_.size()) |
301 << "Calls Create() before calling this method"; | 281 << "Calls Create() before calling this method"; |
302 media::AudioOutputController* controller = | 282 media::AudioOutputController* controller = |
303 host_->audio_entries_.begin()->second->controller; | 283 host_->audio_entries_.begin()->second->controller; |
304 CHECK(controller) << "AudioOutputController not found"; | 284 CHECK(controller) << "AudioOutputController not found"; |
305 | 285 |
306 // Expect an error signal sent through IPC. | 286 // Expect an error signal sent through IPC. |
307 EXPECT_CALL(*host_, OnStreamError(kRouteId, kStreamId)); | 287 EXPECT_CALL(*host_, OnStreamError(kStreamId)); |
308 | 288 |
309 // Simulate an error sent from the audio device. | 289 // Simulate an error sent from the audio device. |
310 host_->OnError(controller, 0); | 290 host_->OnError(controller, 0); |
311 SyncWithAudioThread(); | 291 SyncWithAudioThread(); |
312 | 292 |
313 // Expect the audio stream record is removed. | 293 // Expect the audio stream record is removed. |
314 EXPECT_EQ(0u, host_->audio_entries_.size()); | 294 EXPECT_EQ(0u, host_->audio_entries_.size()); |
315 } | 295 } |
316 | 296 |
317 // Called on the audio thread. | 297 // Called on the audio thread. |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 | 458 |
479 // Simulate the case where a stream is not properly closed. | 459 // Simulate the case where a stream is not properly closed. |
480 TEST_F(AudioRendererHostTest, CreateLowLatencyAndShutdown) { | 460 TEST_F(AudioRendererHostTest, CreateLowLatencyAndShutdown) { |
481 if (!IsRunningHeadless()) | 461 if (!IsRunningHeadless()) |
482 EnableRealDevice(); | 462 EnableRealDevice(); |
483 | 463 |
484 CreateLowLatency(); | 464 CreateLowLatency(); |
485 } | 465 } |
486 | 466 |
487 // TODO(hclam): Add tests for data conversation in low latency mode. | 467 // TODO(hclam): Add tests for data conversation in low latency mode. |
OLD | NEW |