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, | |
60 void(int stream_id, int length)); | |
61 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); | 57 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); |
62 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); | 58 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); |
63 MOCK_METHOD1(OnStreamError, void(int stream_id)); | 59 MOCK_METHOD1(OnStreamError, void(int stream_id)); |
64 MOCK_METHOD2(OnStreamVolume, void(int stream_id, double volume)); | 60 MOCK_METHOD2(OnStreamVolume, void(int stream_id, double volume)); |
65 | 61 |
66 base::SharedMemory* shared_memory() { return shared_memory_.get(); } | 62 base::SharedMemory* shared_memory() { return shared_memory_.get(); } |
67 uint32 shared_memory_length() { return shared_memory_length_; } | 63 uint32 shared_memory_length() { return shared_memory_length_; } |
68 | 64 |
69 base::SyncSocket* sync_socket() { return sync_socket_.get(); } | 65 base::SyncSocket* sync_socket() { return sync_socket_.get(); } |
70 | 66 |
71 private: | 67 private: |
72 // This method is used to dispatch IPC messages to the renderer. We intercept | 68 // 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 | 69 // these messages here and dispatch to our mock methods to verify the |
74 // conversation between this object and the renderer. | 70 // conversation between this object and the renderer. |
75 virtual bool Send(IPC::Message* message) { | 71 virtual bool Send(IPC::Message* message) { |
76 CHECK(message); | 72 CHECK(message); |
77 | 73 |
78 // In this method we dispatch the messages to the according handlers as if | 74 // In this method we dispatch the messages to the according handlers as if |
79 // we are the renderer. | 75 // we are the renderer. |
80 bool handled = true; | 76 bool handled = true; |
81 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) | 77 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) |
82 IPC_MESSAGE_HANDLER(AudioMsg_RequestPacket, OnRequestPacket) | 78 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated, |
83 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated, OnStreamCreated) | 79 OnStreamCreated) |
84 IPC_MESSAGE_HANDLER(AudioMsg_NotifyLowLatencyStreamCreated, | |
85 OnLowLatencyStreamCreated) | |
86 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, | 80 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, |
87 OnStreamStateChanged) | 81 OnStreamStateChanged) |
88 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamVolume, OnStreamVolume) | |
89 IPC_MESSAGE_UNHANDLED(handled = false) | 82 IPC_MESSAGE_UNHANDLED(handled = false) |
90 IPC_END_MESSAGE_MAP() | 83 IPC_END_MESSAGE_MAP() |
91 EXPECT_TRUE(handled); | 84 EXPECT_TRUE(handled); |
92 | 85 |
93 delete message; | 86 delete message; |
94 return true; | 87 return true; |
95 } | 88 } |
96 | 89 |
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, | 90 void OnStreamCreated(const IPC::Message& msg, int stream_id, |
104 base::SharedMemoryHandle handle, uint32 length) { | 91 base::SharedMemoryHandle handle, |
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, | |
116 base::SharedMemoryHandle handle, | |
117 #if defined(OS_WIN) | 92 #if defined(OS_WIN) |
118 base::SyncSocket::Handle socket_handle, | 93 base::SyncSocket::Handle socket_handle, |
119 #else | 94 #else |
120 base::FileDescriptor socket_descriptor, | 95 base::FileDescriptor socket_descriptor, |
121 #endif | 96 #endif |
122 uint32 length) { | 97 uint32 length) { |
123 // Maps the shared memory. | 98 // Maps the shared memory. |
124 shared_memory_.reset(new base::SharedMemory(handle, false)); | 99 shared_memory_.reset(new base::SharedMemory(handle, false)); |
125 CHECK(shared_memory_->Map(length)); | 100 CHECK(shared_memory_->Map(length)); |
126 CHECK(shared_memory_->memory()); | 101 CHECK(shared_memory_->memory()); |
127 shared_memory_length_ = length; | 102 shared_memory_length_ = length; |
128 | 103 |
129 // Create the SyncSocket using the handle. | 104 // Create the SyncSocket using the handle. |
130 base::SyncSocket::Handle sync_socket_handle; | 105 base::SyncSocket::Handle sync_socket_handle; |
131 #if defined(OS_WIN) | 106 #if defined(OS_WIN) |
132 sync_socket_handle = socket_handle; | 107 sync_socket_handle = socket_handle; |
133 #else | 108 #else |
134 sync_socket_handle = socket_descriptor.fd; | 109 sync_socket_handle = socket_descriptor.fd; |
135 #endif | 110 #endif |
136 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); | 111 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); |
137 | 112 |
138 // And then delegate the call to the mock method. | 113 // And then delegate the call to the mock method. |
139 OnLowLatencyStreamCreated(stream_id, length); | 114 OnStreamCreated(stream_id, length); |
140 } | 115 } |
141 | 116 |
142 void OnStreamStateChanged(const IPC::Message& msg, int stream_id, | 117 void OnStreamStateChanged(const IPC::Message& msg, int stream_id, |
143 AudioStreamState state) { | 118 AudioStreamState state) { |
144 if (state == kAudioStreamPlaying) { | 119 if (state == kAudioStreamPlaying) { |
145 OnStreamPlaying(stream_id); | 120 OnStreamPlaying(stream_id); |
146 } else if (state == kAudioStreamPaused) { | 121 } else if (state == kAudioStreamPaused) { |
147 OnStreamPaused(stream_id); | 122 OnStreamPaused(stream_id); |
148 } else if (state == kAudioStreamError) { | 123 } else if (state == kAudioStreamError) { |
149 OnStreamError(stream_id); | 124 OnStreamError(stream_id); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 io_thread_.reset(); | 192 io_thread_.reset(); |
218 ui_thread_.reset(); | 193 ui_thread_.reset(); |
219 } | 194 } |
220 | 195 |
221 void Create() { | 196 void Create() { |
222 EXPECT_CALL(*observer_, | 197 EXPECT_CALL(*observer_, |
223 OnSetAudioStreamStatus(_, kStreamId, "created")); | 198 OnSetAudioStreamStatus(_, kStreamId, "created")); |
224 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)); | 199 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)); |
225 | 200 |
226 InSequence s; | 201 InSequence s; |
227 // 1. We will first receive a OnStreamCreated() signal. | 202 // We will first receive an OnStreamCreated() signal. |
228 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)); | 203 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())); | 204 .WillOnce(QuitMessageLoop(message_loop_.get())); |
233 | 205 |
234 AudioParameters params; | 206 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. | |
257 EXPECT_CALL(*host_, | |
258 OnLowLatencyStreamCreated(kStreamId, _)) | |
259 .WillOnce(QuitMessageLoop(message_loop_.get())); | |
260 | |
261 AudioParameters params; | |
262 if (mock_stream_) | 207 if (mock_stream_) |
263 params.format = AudioParameters::AUDIO_MOCK; | 208 params.format = AudioParameters::AUDIO_MOCK; |
264 else | 209 else |
265 params.format = AudioParameters::AUDIO_PCM_LINEAR; | 210 params.format = AudioParameters::AUDIO_PCM_LINEAR; |
266 params.channels = 2; | 211 params.channels = 2; |
267 params.sample_rate = AudioParameters::kAudioCDSampleRate; | 212 params.sample_rate = AudioParameters::kAudioCDSampleRate; |
268 params.bits_per_sample = 16; | 213 params.bits_per_sample = 16; |
269 params.samples_per_packet = 0; | 214 params.samples_per_packet = 0; |
270 | 215 |
271 // Send a create stream message to the audio output stream and wait until | 216 // Send a create stream message to the audio output stream and wait until |
272 // we receive the created message. | 217 // we receive the created message. |
273 host_->OnCreateStream(kStreamId, params, true); | 218 host_->OnCreateStream(kStreamId, params); |
274 message_loop_->Run(); | 219 message_loop_->Run(); |
275 } | 220 } |
276 | 221 |
277 void Close() { | 222 void Close() { |
278 EXPECT_CALL(*observer_, | 223 EXPECT_CALL(*observer_, |
279 OnSetAudioStreamStatus(_, kStreamId, "closed")); | 224 OnSetAudioStreamStatus(_, kStreamId, "closed")); |
280 | 225 |
281 // Send a message to AudioRendererHost to tell it we want to close the | 226 // Send a message to AudioRendererHost to tell it we want to close the |
282 // stream. | 227 // stream. |
283 host_->OnCloseStream(kStreamId); | 228 host_->OnCloseStream(kStreamId); |
(...skipping 21 matching lines...) Expand all Loading... |
305 } | 250 } |
306 | 251 |
307 void SetVolume(double volume) { | 252 void SetVolume(double volume) { |
308 EXPECT_CALL(*observer_, | 253 EXPECT_CALL(*observer_, |
309 OnSetAudioStreamVolume(_, kStreamId, volume)); | 254 OnSetAudioStreamVolume(_, kStreamId, volume)); |
310 | 255 |
311 host_->OnSetVolume(kStreamId, volume); | 256 host_->OnSetVolume(kStreamId, volume); |
312 message_loop_->RunAllPending(); | 257 message_loop_->RunAllPending(); |
313 } | 258 } |
314 | 259 |
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() { | 260 void SimulateError() { |
325 EXPECT_CALL(*observer_, | 261 EXPECT_CALL(*observer_, |
326 OnSetAudioStreamStatus(_, kStreamId, "error")); | 262 OnSetAudioStreamStatus(_, kStreamId, "error")); |
327 // Find the first AudioOutputController in the AudioRendererHost. | 263 // Find the first AudioOutputController in the AudioRendererHost. |
328 CHECK(host_->audio_entries_.size()) | 264 CHECK(host_->audio_entries_.size()) |
329 << "Calls Create() before calling this method"; | 265 << "Calls Create() before calling this method"; |
330 media::AudioOutputController* controller = | 266 media::AudioOutputController* controller = |
331 host_->audio_entries_.begin()->second->controller; | 267 host_->audio_entries_.begin()->second->controller; |
332 CHECK(controller) << "AudioOutputController not found"; | 268 CHECK(controller) << "AudioOutputController not found"; |
333 | 269 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 }; | 321 }; |
386 | 322 |
387 TEST_F(AudioRendererHostTest, CreateAndClose) { | 323 TEST_F(AudioRendererHostTest, CreateAndClose) { |
388 if (!IsRunningHeadless()) | 324 if (!IsRunningHeadless()) |
389 EnableRealDevice(); | 325 EnableRealDevice(); |
390 | 326 |
391 Create(); | 327 Create(); |
392 Close(); | 328 Close(); |
393 } | 329 } |
394 | 330 |
| 331 // Simulate the case where a stream is not properly closed. |
| 332 TEST_F(AudioRendererHostTest, CreateAndShutdown) { |
| 333 if (!IsRunningHeadless()) |
| 334 EnableRealDevice(); |
| 335 |
| 336 Create(); |
| 337 } |
| 338 |
395 TEST_F(AudioRendererHostTest, CreatePlayAndClose) { | 339 TEST_F(AudioRendererHostTest, CreatePlayAndClose) { |
396 if (!IsRunningHeadless()) | 340 if (!IsRunningHeadless()) |
397 EnableRealDevice(); | 341 EnableRealDevice(); |
398 | 342 |
399 Create(); | 343 Create(); |
400 Play(); | 344 Play(); |
401 Close(); | 345 Close(); |
402 } | 346 } |
403 | 347 |
404 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) { | 348 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) { |
(...skipping 16 matching lines...) Expand all Loading... |
421 Pause(); | 365 Pause(); |
422 Close(); | 366 Close(); |
423 | 367 |
424 // Expect the volume is set. | 368 // Expect the volume is set. |
425 if (IsRunningHeadless()) { | 369 if (IsRunningHeadless()) { |
426 EXPECT_EQ(0.5, FakeAudioOutputStream::GetLastFakeStream()->volume()); | 370 EXPECT_EQ(0.5, FakeAudioOutputStream::GetLastFakeStream()->volume()); |
427 } | 371 } |
428 } | 372 } |
429 | 373 |
430 // Simulate the case where a stream is not properly closed. | 374 // 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) { | 375 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) { |
440 if (!IsRunningHeadless()) | 376 if (!IsRunningHeadless()) |
441 EnableRealDevice(); | 377 EnableRealDevice(); |
442 | 378 |
443 Create(); | 379 Create(); |
444 Play(); | 380 Play(); |
445 } | 381 } |
446 | 382 |
447 // Simulate the case where a stream is not properly closed. | 383 // Simulate the case where a stream is not properly closed. |
448 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) { | 384 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) { |
449 if (!IsRunningHeadless()) | 385 if (!IsRunningHeadless()) |
450 EnableRealDevice(); | 386 EnableRealDevice(); |
451 | 387 |
452 Create(); | 388 Create(); |
453 Play(); | 389 Play(); |
454 Pause(); | 390 Pause(); |
455 } | 391 } |
456 | 392 |
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) { | 393 TEST_F(AudioRendererHostTest, SimulateError) { |
485 if (!IsRunningHeadless()) | 394 if (!IsRunningHeadless()) |
486 EnableRealDevice(); | 395 EnableRealDevice(); |
487 | 396 |
488 Create(); | 397 Create(); |
489 Play(); | 398 Play(); |
490 SimulateError(); | 399 SimulateError(); |
491 } | 400 } |
492 | 401 |
493 // Simulate the case when an error is generated on the browser process, | 402 // 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 | 403 // the audio device is closed but the render process try to close the |
495 // audio stream again. | 404 // audio stream again. |
496 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { | 405 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { |
497 if (!IsRunningHeadless()) | 406 if (!IsRunningHeadless()) |
498 EnableRealDevice(); | 407 EnableRealDevice(); |
499 | 408 |
500 Create(); | 409 Create(); |
501 Play(); | 410 Play(); |
502 SimulateError(); | 411 SimulateError(); |
503 Close(); | 412 Close(); |
504 } | 413 } |
505 | 414 |
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 | 415 |
522 // TODO(hclam): Add tests for data conversation in low latency mode. | 416 // TODO(hclam): Add tests for data conversation in low latency mode. |
OLD | NEW |