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/bind.h" | 5 #include "base/bind.h" |
6 #include "base/environment.h" | 6 #include "base/environment.h" |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.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/sync_socket.h" | 10 #include "base/sync_socket.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 explicit MockAudioRendererHost( | 45 explicit MockAudioRendererHost( |
46 const content::ResourceContext* resource_context) | 46 const content::ResourceContext* resource_context) |
47 : AudioRendererHost(resource_context), | 47 : AudioRendererHost(resource_context), |
48 shared_memory_length_(0) { | 48 shared_memory_length_(0) { |
49 } | 49 } |
50 | 50 |
51 virtual ~MockAudioRendererHost() { | 51 virtual ~MockAudioRendererHost() { |
52 } | 52 } |
53 | 53 |
54 // A list of mock methods. | 54 // A list of mock methods. |
55 MOCK_METHOD2(OnRequestPacket, | |
56 void(int stream_id, AudioBuffersState buffers_state)); | |
57 MOCK_METHOD2(OnStreamCreated, | 55 MOCK_METHOD2(OnStreamCreated, |
58 void(int stream_id, int length)); | 56 void(int stream_id, int length)); |
59 MOCK_METHOD2(OnLowLatencyStreamCreated, | 57 MOCK_METHOD2(OnLowLatencyStreamCreated, |
60 void(int stream_id, int length)); | 58 void(int stream_id, int length)); |
61 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); | 59 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); |
62 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); | 60 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); |
63 MOCK_METHOD1(OnStreamError, void(int stream_id)); | 61 MOCK_METHOD1(OnStreamError, void(int stream_id)); |
64 MOCK_METHOD2(OnStreamVolume, void(int stream_id, double volume)); | 62 MOCK_METHOD2(OnStreamVolume, void(int stream_id, double volume)); |
65 | 63 |
66 base::SharedMemory* shared_memory() { return shared_memory_.get(); } | 64 base::SharedMemory* shared_memory() { return shared_memory_.get(); } |
67 uint32 shared_memory_length() { return shared_memory_length_; } | 65 uint32 shared_memory_length() { return shared_memory_length_; } |
68 | 66 |
69 base::SyncSocket* sync_socket() { return sync_socket_.get(); } | 67 base::SyncSocket* sync_socket() { return sync_socket_.get(); } |
70 | 68 |
71 private: | 69 private: |
72 // This method is used to dispatch IPC messages to the renderer. We intercept | 70 // This method is used to dispatch IPC messages to the renderer. We intercept |
73 // these messages here and dispatch to our mock methods to verify the | 71 // these messages here and dispatch to our mock methods to verify the |
74 // conversation between this object and the renderer. | 72 // conversation between this object and the renderer. |
75 virtual bool Send(IPC::Message* message) { | 73 virtual bool Send(IPC::Message* message) { |
76 CHECK(message); | 74 CHECK(message); |
77 | 75 |
78 // In this method we dispatch the messages to the according handlers as if | 76 // In this method we dispatch the messages to the according handlers as if |
79 // we are the renderer. | 77 // we are the renderer. |
80 bool handled = true; | 78 bool handled = true; |
81 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) | 79 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) |
82 IPC_MESSAGE_HANDLER(AudioMsg_RequestPacket, OnRequestPacket) | |
83 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated, OnStreamCreated) | |
84 IPC_MESSAGE_HANDLER(AudioMsg_NotifyLowLatencyStreamCreated, | 80 IPC_MESSAGE_HANDLER(AudioMsg_NotifyLowLatencyStreamCreated, |
85 OnLowLatencyStreamCreated) | 81 OnLowLatencyStreamCreated) |
86 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, | 82 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, |
87 OnStreamStateChanged) | 83 OnStreamStateChanged) |
88 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamVolume, OnStreamVolume) | 84 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamVolume, OnStreamVolume) |
89 IPC_MESSAGE_UNHANDLED(handled = false) | 85 IPC_MESSAGE_UNHANDLED(handled = false) |
90 IPC_END_MESSAGE_MAP() | 86 IPC_END_MESSAGE_MAP() |
91 EXPECT_TRUE(handled); | 87 EXPECT_TRUE(handled); |
92 | 88 |
93 delete message; | 89 delete message; |
94 return true; | 90 return true; |
95 } | 91 } |
96 | 92 |
97 // These handler methods do minimal things and delegate to the mock methods. | |
98 void OnRequestPacket(const IPC::Message& msg, int stream_id, | |
99 AudioBuffersState buffers_state) { | |
100 OnRequestPacket(stream_id, buffers_state); | |
101 } | |
102 | |
103 void OnStreamCreated(const IPC::Message& msg, int stream_id, | |
104 base::SharedMemoryHandle handle, uint32 length) { | |
105 // Maps the shared memory. | |
106 shared_memory_.reset(new base::SharedMemory(handle, false)); | |
107 ASSERT_TRUE(shared_memory_->Map(length)); | |
108 ASSERT_TRUE(shared_memory_->memory()); | |
109 shared_memory_length_ = length; | |
110 | |
111 // And then delegate the call to the mock method. | |
112 OnStreamCreated(stream_id, length); | |
113 } | |
114 | |
115 void OnLowLatencyStreamCreated(const IPC::Message& msg, int stream_id, | 93 void OnLowLatencyStreamCreated(const IPC::Message& msg, int stream_id, |
116 base::SharedMemoryHandle handle, | 94 base::SharedMemoryHandle handle, |
117 #if defined(OS_WIN) | 95 #if defined(OS_WIN) |
118 base::SyncSocket::Handle socket_handle, | 96 base::SyncSocket::Handle socket_handle, |
119 #else | 97 #else |
120 base::FileDescriptor socket_descriptor, | 98 base::FileDescriptor socket_descriptor, |
121 #endif | 99 #endif |
122 uint32 length) { | 100 uint32 length) { |
123 // Maps the shared memory. | 101 // Maps the shared memory. |
124 shared_memory_.reset(new base::SharedMemory(handle, false)); | 102 shared_memory_.reset(new base::SharedMemory(handle, false)); |
125 CHECK(shared_memory_->Map(length)); | 103 CHECK(shared_memory_->Map(length)); |
126 CHECK(shared_memory_->memory()); | 104 CHECK(shared_memory_->memory()); |
127 shared_memory_length_ = length; | 105 shared_memory_length_ = length; |
128 | 106 |
129 // Create the SyncSocket using the handle. | 107 // Create the SyncSocket using the handle. |
130 base::SyncSocket::Handle sync_socket_handle; | 108 base::SyncSocket::Handle sync_socket_handle; |
131 #if defined(OS_WIN) | 109 #if defined(OS_WIN) |
132 sync_socket_handle = socket_handle; | 110 sync_socket_handle = socket_handle; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 io_thread_.reset(); | 195 io_thread_.reset(); |
218 ui_thread_.reset(); | 196 ui_thread_.reset(); |
219 } | 197 } |
220 | 198 |
221 void Create() { | 199 void Create() { |
222 EXPECT_CALL(*observer_, | 200 EXPECT_CALL(*observer_, |
223 OnSetAudioStreamStatus(_, kStreamId, "created")); | 201 OnSetAudioStreamStatus(_, kStreamId, "created")); |
224 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)); | 202 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)); |
225 | 203 |
226 InSequence s; | 204 InSequence s; |
227 // 1. We will first receive a OnStreamCreated() signal. | |
228 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)); | |
229 | |
230 // 2. First packet request will arrive. | |
231 EXPECT_CALL(*host_, OnRequestPacket(kStreamId, _)) | |
232 .WillOnce(QuitMessageLoop(message_loop_.get())); | |
233 | |
234 AudioParameters params; | |
235 if (mock_stream_) | |
236 params.format = AudioParameters::AUDIO_MOCK; | |
237 else | |
238 params.format = AudioParameters::AUDIO_PCM_LINEAR; | |
239 params.channels = 2; | |
240 params.sample_rate = AudioParameters::kAudioCDSampleRate; | |
241 params.bits_per_sample = 16; | |
242 params.samples_per_packet = 0; | |
243 | |
244 // Send a create stream message to the audio output stream and wait until | |
245 // we receive the created message. | |
246 host_->OnCreateStream(kStreamId, params, false); | |
247 message_loop_->Run(); | |
248 } | |
249 | |
250 void CreateLowLatency() { | |
251 EXPECT_CALL(*observer_, | |
252 OnSetAudioStreamStatus(_, kStreamId, "created")); | |
253 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)); | |
254 | |
255 InSequence s; | |
256 // We will first receive a OnLowLatencyStreamCreated() signal. | 205 // We will first receive a OnLowLatencyStreamCreated() signal. |
257 EXPECT_CALL(*host_, | 206 EXPECT_CALL(*host_, |
258 OnLowLatencyStreamCreated(kStreamId, _)) | 207 OnLowLatencyStreamCreated(kStreamId, _)) |
259 .WillOnce(QuitMessageLoop(message_loop_.get())); | 208 .WillOnce(QuitMessageLoop(message_loop_.get())); |
260 | 209 |
261 AudioParameters params; | 210 AudioParameters params; |
262 if (mock_stream_) | 211 if (mock_stream_) |
263 params.format = AudioParameters::AUDIO_MOCK; | 212 params.format = AudioParameters::AUDIO_MOCK; |
264 else | 213 else |
265 params.format = AudioParameters::AUDIO_PCM_LINEAR; | 214 params.format = AudioParameters::AUDIO_PCM_LINEAR; |
266 params.channels = 2; | 215 params.channels = 2; |
267 params.sample_rate = AudioParameters::kAudioCDSampleRate; | 216 params.sample_rate = AudioParameters::kAudioCDSampleRate; |
268 params.bits_per_sample = 16; | 217 params.bits_per_sample = 16; |
269 params.samples_per_packet = 0; | 218 params.samples_per_packet = 0; |
270 | 219 |
271 // Send a create stream message to the audio output stream and wait until | 220 // Send a create stream message to the audio output stream and wait until |
272 // we receive the created message. | 221 // we receive the created message. |
273 host_->OnCreateStream(kStreamId, params, true); | 222 host_->OnCreateStream(kStreamId, params); |
274 message_loop_->Run(); | 223 message_loop_->Run(); |
275 } | 224 } |
276 | 225 |
277 void Close() { | 226 void Close() { |
278 EXPECT_CALL(*observer_, | 227 EXPECT_CALL(*observer_, |
279 OnSetAudioStreamStatus(_, kStreamId, "closed")); | 228 OnSetAudioStreamStatus(_, kStreamId, "closed")); |
280 | 229 |
281 // Send a message to AudioRendererHost to tell it we want to close the | 230 // Send a message to AudioRendererHost to tell it we want to close the |
282 // stream. | 231 // stream. |
283 host_->OnCloseStream(kStreamId); | 232 host_->OnCloseStream(kStreamId); |
(...skipping 21 matching lines...) Expand all Loading... |
305 } | 254 } |
306 | 255 |
307 void SetVolume(double volume) { | 256 void SetVolume(double volume) { |
308 EXPECT_CALL(*observer_, | 257 EXPECT_CALL(*observer_, |
309 OnSetAudioStreamVolume(_, kStreamId, volume)); | 258 OnSetAudioStreamVolume(_, kStreamId, volume)); |
310 | 259 |
311 host_->OnSetVolume(kStreamId, volume); | 260 host_->OnSetVolume(kStreamId, volume); |
312 message_loop_->RunAllPending(); | 261 message_loop_->RunAllPending(); |
313 } | 262 } |
314 | 263 |
315 void NotifyPacketReady() { | |
316 EXPECT_CALL(*host_, OnRequestPacket(kStreamId, _)) | |
317 .WillOnce(QuitMessageLoop(message_loop_.get())); | |
318 | |
319 memset(host_->shared_memory()->memory(), 0, host_->shared_memory_length()); | |
320 host_->OnNotifyPacketReady(kStreamId, host_->shared_memory_length()); | |
321 message_loop_->Run(); | |
322 } | |
323 | |
324 void SimulateError() { | 264 void SimulateError() { |
325 EXPECT_CALL(*observer_, | 265 EXPECT_CALL(*observer_, |
326 OnSetAudioStreamStatus(_, kStreamId, "error")); | 266 OnSetAudioStreamStatus(_, kStreamId, "error")); |
327 // Find the first AudioOutputController in the AudioRendererHost. | 267 // Find the first AudioOutputController in the AudioRendererHost. |
328 CHECK(host_->audio_entries_.size()) | 268 CHECK(host_->audio_entries_.size()) |
329 << "Calls Create() before calling this method"; | 269 << "Calls Create() before calling this method"; |
330 media::AudioOutputController* controller = | 270 media::AudioOutputController* controller = |
331 host_->audio_entries_.begin()->second->controller; | 271 host_->audio_entries_.begin()->second->controller; |
332 CHECK(controller) << "AudioOutputController not found"; | 272 CHECK(controller) << "AudioOutputController not found"; |
333 | 273 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 }; | 325 }; |
386 | 326 |
387 TEST_F(AudioRendererHostTest, CreateAndClose) { | 327 TEST_F(AudioRendererHostTest, CreateAndClose) { |
388 if (!IsRunningHeadless()) | 328 if (!IsRunningHeadless()) |
389 EnableRealDevice(); | 329 EnableRealDevice(); |
390 | 330 |
391 Create(); | 331 Create(); |
392 Close(); | 332 Close(); |
393 } | 333 } |
394 | 334 |
| 335 // Simulate the case where a stream is not properly closed. |
| 336 TEST_F(AudioRendererHostTest, CreateAndShutdown) { |
| 337 if (!IsRunningHeadless()) |
| 338 EnableRealDevice(); |
| 339 |
| 340 Create(); |
| 341 } |
| 342 |
395 TEST_F(AudioRendererHostTest, CreatePlayAndClose) { | 343 TEST_F(AudioRendererHostTest, CreatePlayAndClose) { |
396 if (!IsRunningHeadless()) | 344 if (!IsRunningHeadless()) |
397 EnableRealDevice(); | 345 EnableRealDevice(); |
398 | 346 |
399 Create(); | 347 Create(); |
400 Play(); | 348 Play(); |
401 Close(); | 349 Close(); |
402 } | 350 } |
403 | 351 |
404 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) { | 352 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) { |
(...skipping 16 matching lines...) Expand all Loading... |
421 Pause(); | 369 Pause(); |
422 Close(); | 370 Close(); |
423 | 371 |
424 // Expect the volume is set. | 372 // Expect the volume is set. |
425 if (IsRunningHeadless()) { | 373 if (IsRunningHeadless()) { |
426 EXPECT_EQ(0.5, FakeAudioOutputStream::GetLastFakeStream()->volume()); | 374 EXPECT_EQ(0.5, FakeAudioOutputStream::GetLastFakeStream()->volume()); |
427 } | 375 } |
428 } | 376 } |
429 | 377 |
430 // Simulate the case where a stream is not properly closed. | 378 // Simulate the case where a stream is not properly closed. |
431 TEST_F(AudioRendererHostTest, CreateAndShutdown) { | |
432 if (!IsRunningHeadless()) | |
433 EnableRealDevice(); | |
434 | |
435 Create(); | |
436 } | |
437 | |
438 // Simulate the case where a stream is not properly closed. | |
439 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) { | 379 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) { |
440 if (!IsRunningHeadless()) | 380 if (!IsRunningHeadless()) |
441 EnableRealDevice(); | 381 EnableRealDevice(); |
442 | 382 |
443 Create(); | 383 Create(); |
444 Play(); | 384 Play(); |
445 } | 385 } |
446 | 386 |
447 // Simulate the case where a stream is not properly closed. | 387 // Simulate the case where a stream is not properly closed. |
448 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) { | 388 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) { |
449 if (!IsRunningHeadless()) | 389 if (!IsRunningHeadless()) |
450 EnableRealDevice(); | 390 EnableRealDevice(); |
451 | 391 |
452 Create(); | 392 Create(); |
453 Play(); | 393 Play(); |
454 Pause(); | 394 Pause(); |
455 } | 395 } |
456 | 396 |
457 TEST_F(AudioRendererHostTest, DataConversationMockStream) { | |
458 Create(); | |
459 | |
460 // Note that we only do notify three times because the buffer capacity is | |
461 // triple of one packet size. | |
462 NotifyPacketReady(); | |
463 NotifyPacketReady(); | |
464 NotifyPacketReady(); | |
465 Close(); | |
466 } | |
467 | |
468 TEST_F(AudioRendererHostTest, DataConversationRealStream) { | |
469 if (IsRunningHeadless()) | |
470 return; | |
471 EnableRealDevice(); | |
472 Create(); | |
473 Play(); | |
474 | |
475 // If this is a real audio device, the data conversation is not limited | |
476 // to the buffer capacity of AudioOutputController. So we do 5 exchanges | |
477 // before we close the device. | |
478 for (int i = 0; i < 5; ++i) { | |
479 NotifyPacketReady(); | |
480 } | |
481 Close(); | |
482 } | |
483 | |
484 TEST_F(AudioRendererHostTest, SimulateError) { | 397 TEST_F(AudioRendererHostTest, SimulateError) { |
485 if (!IsRunningHeadless()) | 398 if (!IsRunningHeadless()) |
486 EnableRealDevice(); | 399 EnableRealDevice(); |
487 | 400 |
488 Create(); | 401 Create(); |
489 Play(); | 402 Play(); |
490 SimulateError(); | 403 SimulateError(); |
491 } | 404 } |
492 | 405 |
493 // Simulate the case when an error is generated on the browser process, | 406 // Simulate the case when an error is generated on the browser process, |
494 // the audio device is closed but the render process try to close the | 407 // the audio device is closed but the render process try to close the |
495 // audio stream again. | 408 // audio stream again. |
496 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { | 409 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { |
497 if (!IsRunningHeadless()) | 410 if (!IsRunningHeadless()) |
498 EnableRealDevice(); | 411 EnableRealDevice(); |
499 | 412 |
500 Create(); | 413 Create(); |
501 Play(); | 414 Play(); |
502 SimulateError(); | 415 SimulateError(); |
503 Close(); | 416 Close(); |
504 } | 417 } |
505 | 418 |
506 TEST_F(AudioRendererHostTest, CreateLowLatencyAndClose) { | |
507 if (!IsRunningHeadless()) | |
508 EnableRealDevice(); | |
509 | |
510 CreateLowLatency(); | |
511 Close(); | |
512 } | |
513 | |
514 // Simulate the case where a stream is not properly closed. | |
515 TEST_F(AudioRendererHostTest, CreateLowLatencyAndShutdown) { | |
516 if (!IsRunningHeadless()) | |
517 EnableRealDevice(); | |
518 | |
519 CreateLowLatency(); | |
520 } | |
521 | 419 |
522 // TODO(hclam): Add tests for data conversation in low latency mode. | 420 // TODO(hclam): Add tests for data conversation in low latency mode. |
OLD | NEW |