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