| 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 |