audio_output_proxy_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 3// found in the LICENSE file. 4 5#include <string> 6 7#include "base/message_loop.h" 8#include "base/message_loop_proxy.h" 9#include "media/audio/audio_output_dispatcher_impl.h" 10#include "media/audio/audio_output_proxy.h" 11#include "media/audio/audio_output_resampler.h" 12#include "media/audio/audio_manager.h" 13#include "media/audio/audio_manager_base.h" 14#include "media/audio/fake_audio_output_stream.h" 15#include "testing/gmock/include/gmock/gmock.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18using ::testing::_; 19using ::testing::AllOf; 20using ::testing::DoAll; 21using ::testing::Field; 22using ::testing::Mock; 23using ::testing::NotNull; 24using ::testing::Return; 25using ::testing::SetArrayArgument; 26using media::AudioBus; 27using media::AudioBuffersState; 28using media::AudioInputStream; 29using media::AudioManager; 30using media::AudioManagerBase; 31using media::AudioOutputDispatcher; 32using media::AudioOutputProxy; 33using media::AudioOutputStream; 34using media::AudioParameters; 35using media::FakeAudioOutputStream; 36 37namespace { 38 39static const int kTestCloseDelayMs = 100; 40 41// Used in the test where we don't want a stream to be closed unexpectedly. 42static const int kTestBigCloseDelaySeconds = 1000; 43 44// Delay between callbacks to AudioSourceCallback::OnMoreData. 45static const int kOnMoreDataCallbackDelayMs = 10; 46 47// Let start run long enough for many OnMoreData callbacks to occur. 48static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10; 49 50class MockAudioOutputStream : public AudioOutputStream { 51 public: 52 MockAudioOutputStream(AudioManagerBase* manager, 53 const AudioParameters& params) 54 : start_called_(false), 55 stop_called_(false), 56 params_(params), 57 fake_output_stream_( 58 FakeAudioOutputStream::MakeFakeStream(manager, params_)) { 59 } 60 61 void Start(AudioSourceCallback* callback) { 62 start_called_ = true; 63 fake_output_stream_->Start(callback); 64 } 65 66 void Stop() { 67 stop_called_ = true; 68 fake_output_stream_->Stop(); 69 } 70 71 ~MockAudioOutputStream() {} 72 73 bool start_called() { return start_called_; } 74 bool stop_called() { return stop_called_; } 75 76 MOCK_METHOD0(Open, bool()); 77 MOCK_METHOD1(SetVolume, void(double volume)); 78 MOCK_METHOD1(GetVolume, void(double* volume)); 79 MOCK_METHOD0(Close, void()); 80 81 private: 82 bool start_called_; 83 bool stop_called_; 84 AudioParameters params_; 85 scoped_ptr<AudioOutputStream> fake_output_stream_; 86}; 87 88class MockAudioManager : public AudioManagerBase { 89 public: 90 MockAudioManager() {} 91 virtual ~MockAudioManager() { 92 Shutdown(); 93 } 94 95 MOCK_METHOD0(HasAudioOutputDevices, bool()); 96 MOCK_METHOD0(HasAudioInputDevices, bool()); 97 MOCK_METHOD0(GetAudioInputDeviceModel, string16()); 98 MOCK_METHOD1(MakeAudioOutputStream, AudioOutputStream*( 99 const AudioParameters& params)); 100 MOCK_METHOD1(MakeAudioOutputStreamProxy, AudioOutputStream*( 101 const AudioParameters& params)); 102 MOCK_METHOD2(MakeAudioInputStream, AudioInputStream*( 103 const AudioParameters& params, const std::string& device_id)); 104 MOCK_METHOD0(ShowAudioInputSettings, void()); 105 MOCK_METHOD0(GetMessageLoop, scoped_refptr<base::MessageLoopProxy>()); 106 MOCK_METHOD1(GetAudioInputDeviceNames, void( 107 media::AudioDeviceNames* device_name)); 108 MOCK_METHOD0(IsRecordingInProcess, bool()); 109 110 MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*( 111 const AudioParameters& params)); 112 MOCK_METHOD1(MakeLowLatencyOutputStream, AudioOutputStream*( 113 const AudioParameters& params)); 114 MOCK_METHOD2(MakeLinearInputStream, AudioInputStream*( 115 const AudioParameters& params, const std::string& device_id)); 116 MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*( 117 const AudioParameters& params, const std::string& device_id)); 118 MOCK_METHOD1(GetPreferredOutputStreamParameters, AudioParameters( 119 const AudioParameters& params)); 120}; 121 122class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { 123 public: 124 int OnMoreData(AudioBus* audio_bus, AudioBuffersState buffers_state) { 125 audio_bus->Zero(); 126 return audio_bus->frames(); 127 } 128 int OnMoreIOData(AudioBus* source, AudioBus* dest, 129 AudioBuffersState buffers_state) { 130 return OnMoreData(dest, buffers_state); 131 } 132 MOCK_METHOD1(OnError, void(AudioOutputStream* stream)); 133}; 134 135} // namespace 136 137namespace media { 138 139class AudioOutputProxyTest : public testing::Test { 140 protected: 141 virtual void SetUp() { 142 EXPECT_CALL(manager_, GetMessageLoop()) 143 .WillRepeatedly(Return(message_loop_.message_loop_proxy())); 144 InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs)); 145 } 146 147 virtual void TearDown() { 148 // All paused proxies should have been closed at this point. 149 EXPECT_EQ(0u, dispatcher_impl_->paused_proxies_); 150 151 // This is necessary to free all proxy objects that have been 152 // closed by the test. 153 message_loop_.RunUntilIdle(); 154 } 155 156 virtual void InitDispatcher(base::TimeDelta close_delay) { 157 // Use a low sample rate and large buffer size when testing otherwise the 158 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e., 159 // RunUntilIdle() will never terminate. 160 params_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, 161 CHANNEL_LAYOUT_STEREO, 8000, 16, 2048); 162 dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(), 163 params_, 164 close_delay); 165 166 // Necessary to know how long the dispatcher will wait before posting 167 // StopStreamTask. 168 pause_delay_ = dispatcher_impl_->pause_delay_; 169 } 170 171 virtual void OnStart() {} 172 173 MockAudioManager& manager() { 174 return manager_; 175 } 176 177 // Wait for the close timer to fire. 178 void WaitForCloseTimer(const int timer_delay_ms) { 179 message_loop_.RunUntilIdle(); // OpenTask() may reset the timer. 180 base::PlatformThread::Sleep( 181 base::TimeDelta::FromMilliseconds(timer_delay_ms) * 2); 182 message_loop_.RunUntilIdle(); 183 } 184 185 // Methods that do actual tests. 186 void OpenAndClose(AudioOutputDispatcher* dispatcher) { 187 MockAudioOutputStream stream(&manager_, params_); 188 189 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 190 .WillOnce(Return(&stream)); 191 EXPECT_CALL(stream, Open()) 192 .WillOnce(Return(true)); 193 EXPECT_CALL(stream, Close()) 194 .Times(1); 195 196 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); 197 EXPECT_TRUE(proxy->Open()); 198 proxy->Close(); 199 WaitForCloseTimer(kTestCloseDelayMs); 200 } 201 202 // Create a stream, and then calls Start() and Stop(). 203 void StartAndStop(AudioOutputDispatcher* dispatcher) { 204 MockAudioOutputStream stream(&manager_, params_); 205 206 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 207 .WillOnce(Return(&stream)); 208 EXPECT_CALL(stream, Open()) 209 .WillOnce(Return(true)); 210 EXPECT_CALL(stream, SetVolume(_)) 211 .Times(1); 212 EXPECT_CALL(stream, Close()) 213 .Times(1); 214 215 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); 216 EXPECT_TRUE(proxy->Open()); 217 218 proxy->Start(&callback_); 219 OnStart(); 220 proxy->Stop(); 221 222 proxy->Close(); 223 WaitForCloseTimer(kTestCloseDelayMs); 224 EXPECT_TRUE(stream.stop_called()); 225 EXPECT_TRUE(stream.start_called()); 226 } 227 228 // Verify that the stream is closed after Stop is called. 229 void CloseAfterStop(AudioOutputDispatcher* dispatcher) { 230 MockAudioOutputStream stream(&manager_, params_); 231 232 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 233 .WillOnce(Return(&stream)); 234 EXPECT_CALL(stream, Open()) 235 .WillOnce(Return(true)); 236 EXPECT_CALL(stream, SetVolume(_)) 237 .Times(1); 238 EXPECT_CALL(stream, Close()) 239 .Times(1); 240 241 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); 242 EXPECT_TRUE(proxy->Open()); 243 244 proxy->Start(&callback_); 245 OnStart(); 246 proxy->Stop(); 247 248 // Wait for StopStream() to post StopStreamTask(). 249 base::PlatformThread::Sleep(pause_delay_ * 2); 250 WaitForCloseTimer(kTestCloseDelayMs); 251 252 // Verify expectation before calling Close(). 253 Mock::VerifyAndClear(&stream); 254 255 proxy->Close(); 256 EXPECT_TRUE(stream.stop_called()); 257 EXPECT_TRUE(stream.start_called()); 258 } 259 260 // Create two streams, but don't start them. Only one device must be open. 261 void TwoStreams(AudioOutputDispatcher* dispatcher) { 262 MockAudioOutputStream stream(&manager_, params_); 263 264 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 265 .WillOnce(Return(&stream)); 266 EXPECT_CALL(stream, Open()) 267 .WillOnce(Return(true)); 268 EXPECT_CALL(stream, Close()) 269 .Times(1); 270 271 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); 272 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); 273 EXPECT_TRUE(proxy1->Open()); 274 EXPECT_TRUE(proxy2->Open()); 275 proxy1->Close(); 276 proxy2->Close(); 277 WaitForCloseTimer(kTestCloseDelayMs); 278 EXPECT_FALSE(stream.stop_called()); 279 EXPECT_FALSE(stream.start_called()); 280 } 281 282 // Open() method failed. 283 void OpenFailed(AudioOutputDispatcher* dispatcher) { 284 MockAudioOutputStream stream(&manager_, params_); 285 286 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 287 .WillOnce(Return(&stream)); 288 EXPECT_CALL(stream, Open()) 289 .WillOnce(Return(false)); 290 EXPECT_CALL(stream, Close()) 291 .Times(1); 292 293 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); 294 EXPECT_FALSE(proxy->Open()); 295 proxy->Close(); 296 WaitForCloseTimer(kTestCloseDelayMs); 297 EXPECT_FALSE(stream.stop_called()); 298 EXPECT_FALSE(stream.start_called()); 299 } 300 301 void CreateAndWait(AudioOutputDispatcher* dispatcher) { 302 MockAudioOutputStream stream(&manager_, params_); 303 304 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 305 .WillOnce(Return(&stream)); 306 EXPECT_CALL(stream, Open()) 307 .WillOnce(Return(true)); 308 EXPECT_CALL(stream, Close()) 309 .Times(1); 310 311 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); 312 EXPECT_TRUE(proxy->Open()); 313 314 // Simulate a delay. 315 base::PlatformThread::Sleep( 316 base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2); 317 message_loop_.RunUntilIdle(); 318 319 // Verify expectation before calling Close(). 320 Mock::VerifyAndClear(&stream); 321 322 proxy->Close(); 323 EXPECT_FALSE(stream.stop_called()); 324 EXPECT_FALSE(stream.start_called()); 325 } 326 327 void TwoStreams_OnePlaying(AudioOutputDispatcher* dispatcher) { 328 MockAudioOutputStream stream1(&manager_, params_); 329 MockAudioOutputStream stream2(&manager_, params_); 330 331 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 332 .WillOnce(Return(&stream1)) 333 .WillOnce(Return(&stream2)); 334 335 EXPECT_CALL(stream1, Open()) 336 .WillOnce(Return(true)); 337 EXPECT_CALL(stream1, SetVolume(_)) 338 .Times(1); 339 EXPECT_CALL(stream1, Close()) 340 .Times(1); 341 342 EXPECT_CALL(stream2, Open()) 343 .WillOnce(Return(true)); 344 EXPECT_CALL(stream2, Close()) 345 .Times(1); 346 347 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); 348 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); 349 EXPECT_TRUE(proxy1->Open()); 350 EXPECT_TRUE(proxy2->Open()); 351 352 proxy1->Start(&callback_); 353 message_loop_.RunUntilIdle(); 354 OnStart(); 355 proxy1->Stop(); 356 357 proxy1->Close(); 358 proxy2->Close(); 359 EXPECT_TRUE(stream1.stop_called()); 360 EXPECT_TRUE(stream1.start_called()); 361 EXPECT_FALSE(stream2.stop_called()); 362 EXPECT_FALSE(stream2.start_called()); 363 } 364 365 void TwoStreams_BothPlaying(AudioOutputDispatcher* dispatcher) { 366 MockAudioOutputStream stream1(&manager_, params_); 367 MockAudioOutputStream stream2(&manager_, params_); 368 369 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 370 .WillOnce(Return(&stream1)) 371 .WillOnce(Return(&stream2)); 372 373 EXPECT_CALL(stream1, Open()) 374 .WillOnce(Return(true)); 375 EXPECT_CALL(stream1, SetVolume(_)) 376 .Times(1); 377 EXPECT_CALL(stream1, Close()) 378 .Times(1); 379 380 EXPECT_CALL(stream2, Open()) 381 .WillOnce(Return(true)); 382 EXPECT_CALL(stream2, SetVolume(_)) 383 .Times(1); 384 EXPECT_CALL(stream2, Close()) 385 .Times(1); 386 387 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); 388 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); 389 EXPECT_TRUE(proxy1->Open()); 390 EXPECT_TRUE(proxy2->Open()); 391 392 proxy1->Start(&callback_); 393 proxy2->Start(&callback_); 394 OnStart(); 395 proxy1->Stop(); 396 proxy2->Stop(); 397 398 proxy1->Close(); 399 proxy2->Close(); 400 EXPECT_TRUE(stream1.stop_called()); 401 EXPECT_TRUE(stream1.start_called()); 402 EXPECT_TRUE(stream2.stop_called()); 403 EXPECT_TRUE(stream2.start_called()); 404 } 405 406 void StartFailed(AudioOutputDispatcher* dispatcher) { 407 MockAudioOutputStream stream(&manager_, params_); 408 409 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 410 .WillOnce(Return(&stream)); 411 EXPECT_CALL(stream, Open()) 412 .WillOnce(Return(true)); 413 EXPECT_CALL(stream, Close()) 414 .Times(1); 415 416 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); 417 EXPECT_TRUE(proxy->Open()); 418 419 // Simulate a delay. 420 base::PlatformThread::Sleep( 421 base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2); 422 message_loop_.RunUntilIdle(); 423 424 // Verify expectation before calling Close(). 425 Mock::VerifyAndClear(&stream); 426 427 // |stream| is closed at this point. Start() should reopen it again. 428 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 429 .Times(2) 430 .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream*>(NULL))); 431 432 EXPECT_CALL(callback_, OnError(_)) 433 .Times(2); 434 435 proxy->Start(&callback_); 436 437 // Double Start() in the error case should be allowed since it's possible a 438 // callback may not have had time to process the OnError() in between. 439 proxy->Stop(); 440 proxy->Start(&callback_); 441 442 Mock::VerifyAndClear(&callback_); 443 444 proxy->Close(); 445 } 446 447 base::MessageLoop message_loop_; 448 scoped_refptr<AudioOutputDispatcherImpl> dispatcher_impl_; 449 base::TimeDelta pause_delay_; 450 MockAudioManager manager_; 451 MockAudioSourceCallback callback_; 452 AudioParameters params_; 453}; 454 455class AudioOutputResamplerTest : public AudioOutputProxyTest { 456 public: 457 virtual void TearDown() { 458 AudioOutputProxyTest::TearDown(); 459 } 460 461 virtual void InitDispatcher(base::TimeDelta close_delay) OVERRIDE { 462 AudioOutputProxyTest::InitDispatcher(close_delay); 463 // Use a low sample rate and large buffer size when testing otherwise the 464 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e., 465 // RunUntilIdle() will never terminate. 466 resampler_params_ = AudioParameters( 467 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 468 16000, 16, 1024); 469 resampler_ = new AudioOutputResampler( 470 &manager(), params_, resampler_params_, close_delay); 471 } 472 473 virtual void OnStart() OVERRIDE { 474 // Let start run for a bit. 475 message_loop_.RunUntilIdle(); 476 base::PlatformThread::Sleep( 477 base::TimeDelta::FromMilliseconds(kStartRunTimeMs)); 478 } 479 480 protected: 481 AudioParameters resampler_params_; 482 scoped_refptr<AudioOutputResampler> resampler_; 483}; 484 485TEST_F(AudioOutputProxyTest, CreateAndClose) { 486 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_); 487 proxy->Close(); 488} 489 490TEST_F(AudioOutputResamplerTest, CreateAndClose) { 491 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); 492 proxy->Close(); 493} 494 495TEST_F(AudioOutputProxyTest, OpenAndClose) { 496 OpenAndClose(dispatcher_impl_); 497} 498 499TEST_F(AudioOutputResamplerTest, OpenAndClose) { 500 OpenAndClose(resampler_); 501} 502 503// Create a stream, and verify that it is closed after kTestCloseDelayMs. 504// if it doesn't start playing. 505TEST_F(AudioOutputProxyTest, CreateAndWait) { 506 CreateAndWait(dispatcher_impl_); 507} 508 509// Create a stream, and verify that it is closed after kTestCloseDelayMs. 510// if it doesn't start playing. 511TEST_F(AudioOutputResamplerTest, CreateAndWait) { 512 CreateAndWait(resampler_); 513} 514 515TEST_F(AudioOutputProxyTest, StartAndStop) { 516 StartAndStop(dispatcher_impl_); 517} 518 519TEST_F(AudioOutputResamplerTest, StartAndStop) { 520 StartAndStop(resampler_); 521} 522 523TEST_F(AudioOutputProxyTest, CloseAfterStop) { 524 CloseAfterStop(dispatcher_impl_); 525} 526 527TEST_F(AudioOutputResamplerTest, CloseAfterStop) { 528 CloseAfterStop(resampler_); 529} 530 531TEST_F(AudioOutputProxyTest, TwoStreams) { 532 TwoStreams(dispatcher_impl_); 533} 534 535TEST_F(AudioOutputResamplerTest, TwoStreams) { 536 TwoStreams(resampler_); 537} 538 539// Two streams: verify that second stream is allocated when the first 540// starts playing. 541TEST_F(AudioOutputProxyTest, TwoStreams_OnePlaying) { 542 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); 543 TwoStreams_OnePlaying(dispatcher_impl_); 544} 545 546TEST_F(AudioOutputResamplerTest, TwoStreams_OnePlaying) { 547 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); 548 TwoStreams_OnePlaying(resampler_); 549} 550 551// Two streams, both are playing. Dispatcher should not open a third stream. 552TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) { 553 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); 554 TwoStreams_BothPlaying(dispatcher_impl_); 555} 556 557TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) { 558 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); 559 TwoStreams_BothPlaying(resampler_); 560} 561 562TEST_F(AudioOutputProxyTest, OpenFailed) { 563 OpenFailed(dispatcher_impl_); 564} 565 566// Start() method failed. 567TEST_F(AudioOutputProxyTest, StartFailed) { 568 StartFailed(dispatcher_impl_); 569} 570 571TEST_F(AudioOutputResamplerTest, StartFailed) { 572 StartFailed(resampler_); 573} 574 575// Simulate AudioOutputStream::Create() failure with a low latency stream and 576// ensure AudioOutputResampler falls back to the high latency path. 577TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) { 578 MockAudioOutputStream stream(&manager_, params_); 579 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 580 .Times(2) 581 .WillOnce(Return(static_cast<AudioOutputStream*>(NULL))) 582 .WillRepeatedly(Return(&stream)); 583 EXPECT_CALL(stream, Open()) 584 .WillOnce(Return(true)); 585 EXPECT_CALL(stream, Close()) 586 .Times(1); 587 588 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); 589 EXPECT_TRUE(proxy->Open()); 590 proxy->Close(); 591 WaitForCloseTimer(kTestCloseDelayMs); 592} 593 594// Simulate AudioOutputStream::Open() failure with a low latency stream and 595// ensure AudioOutputResampler falls back to the high latency path. 596TEST_F(AudioOutputResamplerTest, LowLatencyOpenFailedFallback) { 597 MockAudioOutputStream failed_stream(&manager_, params_); 598 MockAudioOutputStream okay_stream(&manager_, params_); 599 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 600 .Times(2) 601 .WillOnce(Return(&failed_stream)) 602 .WillRepeatedly(Return(&okay_stream)); 603 EXPECT_CALL(failed_stream, Open()) 604 .WillOnce(Return(false)); 605 EXPECT_CALL(failed_stream, Close()) 606 .Times(1); 607 EXPECT_CALL(okay_stream, Open()) 608 .WillOnce(Return(true)); 609 EXPECT_CALL(okay_stream, Close()) 610 .Times(1); 611 612 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); 613 EXPECT_TRUE(proxy->Open()); 614 proxy->Close(); 615 WaitForCloseTimer(kTestCloseDelayMs); 616} 617 618// Simulate failures to open both the low latency and the fallback high latency 619// stream and ensure AudioOutputResampler falls back to a fake stream. 620TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) { 621 MockAudioOutputStream okay_stream(&manager_, params_); 622 623// Only Windows has a high latency output driver that is not the same as the low 624// latency path. 625#if defined(OS_WIN) 626 static const int kFallbackCount = 2; 627#else 628 static const int kFallbackCount = 1; 629#endif 630 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 631 .Times(kFallbackCount) 632 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL))); 633 634 // To prevent shared memory issues the sample rate and buffer size should 635 // match the input stream parameters. 636 EXPECT_CALL(manager(), MakeAudioOutputStream(AllOf( 637 testing::Property(&AudioParameters::format, AudioParameters::AUDIO_FAKE), 638 testing::Property(&AudioParameters::sample_rate, params_.sample_rate()), 639 testing::Property( 640 &AudioParameters::frames_per_buffer, params_.frames_per_buffer())))) 641 .Times(1) 642 .WillOnce(Return(&okay_stream)); 643 EXPECT_CALL(okay_stream, Open()) 644 .WillOnce(Return(true)); 645 EXPECT_CALL(okay_stream, Close()) 646 .Times(1); 647 648 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); 649 EXPECT_TRUE(proxy->Open()); 650 proxy->Close(); 651 WaitForCloseTimer(kTestCloseDelayMs); 652} 653 654// Simulate failures to open both the low latency, the fallback high latency 655// stream, and the fake audio output stream and ensure AudioOutputResampler 656// terminates normally. 657TEST_F(AudioOutputResamplerTest, AllFallbackFailed) { 658// Only Windows has a high latency output driver that is not the same as the low 659// latency path. 660#if defined(OS_WIN) 661 static const int kFallbackCount = 3; 662#else 663 static const int kFallbackCount = 2; 664#endif 665 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 666 .Times(kFallbackCount) 667 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL))); 668 669 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); 670 EXPECT_FALSE(proxy->Open()); 671 proxy->Close(); 672 WaitForCloseTimer(kTestCloseDelayMs); 673} 674 675// Simulate an eventual OpenStream() failure; i.e. successful OpenStream() calls 676// eventually followed by one which fails; root cause of http://crbug.com/150619 677TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) { 678 MockAudioOutputStream stream1(&manager_, params_); 679 MockAudioOutputStream stream2(&manager_, params_); 680 MockAudioOutputStream stream3(&manager_, params_); 681 682 // Setup the mock such that all three streams are successfully created. 683 EXPECT_CALL(manager(), MakeAudioOutputStream(_)) 684 .WillOnce(Return(&stream1)) 685 .WillOnce(Return(&stream2)) 686 .WillOnce(Return(&stream3)) 687 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL))); 688 689 // Stream1 should be able to successfully open and start. 690 EXPECT_CALL(stream1, Open()) 691 .WillOnce(Return(true)); 692 EXPECT_CALL(stream1, Close()) 693 .Times(1); 694 EXPECT_CALL(stream1, SetVolume(_)) 695 .Times(1); 696 697 // Stream2 should also be able to successfully open and start. 698 EXPECT_CALL(stream2, Open()) 699 .WillOnce(Return(true)); 700 EXPECT_CALL(stream2, Close()) 701 .Times(1); 702 EXPECT_CALL(stream2, SetVolume(_)) 703 .Times(1); 704 705 // Stream3 should fail on Open() (yet still be closed since 706 // MakeAudioOutputStream returned a valid AudioOutputStream object). 707 EXPECT_CALL(stream3, Open()) 708 .WillOnce(Return(false)); 709 EXPECT_CALL(stream3, Close()) 710 .Times(1); 711 712 // Open and start the first proxy and stream. 713 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_); 714 EXPECT_TRUE(proxy1->Open()); 715 proxy1->Start(&callback_); 716 OnStart(); 717 718 // Open and start the second proxy and stream. 719 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_); 720 EXPECT_TRUE(proxy2->Open()); 721 proxy2->Start(&callback_); 722 OnStart(); 723 724 // Attempt to open the third stream which should fail. 725 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_); 726 EXPECT_FALSE(proxy3->Open()); 727 728 // Perform the required Stop()/Close() shutdown dance for each proxy. Under 729 // the hood each proxy should correctly call CloseStream() if OpenStream() 730 // succeeded or not. 731 proxy3->Stop(); 732 proxy3->Close(); 733 proxy2->Stop(); 734 proxy2->Close(); 735 proxy1->Stop(); 736 proxy1->Close(); 737 738 // Wait for all of the messages to fly and then verify stream behavior. 739 WaitForCloseTimer(kTestCloseDelayMs); 740 EXPECT_TRUE(stream1.stop_called()); 741 EXPECT_TRUE(stream1.start_called()); 742 EXPECT_TRUE(stream2.stop_called()); 743 EXPECT_TRUE(stream2.start_called()); 744 EXPECT_FALSE(stream3.stop_called()); 745 EXPECT_FALSE(stream3.start_called()); 746} 747 748} // namespace media 749