Change blimp README to use Markdown.
[chromium-blink-merge.git] / media / audio / audio_output_proxy_unittest.cc
blob6f8befb74a1fe7dafaf396d19afae895c09d53c1
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.
5 #include <string>
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"
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::AudioInputStream;
29 using media::AudioManager;
30 using media::AudioManagerBase;
31 using media::AudioOutputDispatcher;
32 using media::AudioOutputProxy;
33 using media::AudioOutputStream;
34 using media::AudioParameters;
35 using media::FakeAudioOutputStream;
37 namespace {
39 static const int kTestCloseDelayMs = 10;
41 // Delay between callbacks to AudioSourceCallback::OnMoreData.
42 static const int kOnMoreDataCallbackDelayMs = 10;
44 // Let start run long enough for many OnMoreData callbacks to occur.
45 static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10;
47 class MockAudioOutputStream : public AudioOutputStream {
48 public:
49 MockAudioOutputStream(AudioManagerBase* manager,
50 const AudioParameters& params)
51 : start_called_(false),
52 stop_called_(false),
53 params_(params),
54 fake_output_stream_(
55 FakeAudioOutputStream::MakeFakeStream(manager, params_)) {
58 void Start(AudioSourceCallback* callback) {
59 start_called_ = true;
60 fake_output_stream_->Start(callback);
63 void Stop() {
64 stop_called_ = true;
65 fake_output_stream_->Stop();
68 ~MockAudioOutputStream() {}
70 bool start_called() { return start_called_; }
71 bool stop_called() { return stop_called_; }
73 MOCK_METHOD0(Open, bool());
74 MOCK_METHOD1(SetVolume, void(double volume));
75 MOCK_METHOD1(GetVolume, void(double* volume));
76 MOCK_METHOD0(Close, void());
78 private:
79 bool start_called_;
80 bool stop_called_;
81 AudioParameters params_;
82 scoped_ptr<AudioOutputStream> fake_output_stream_;
85 class MockAudioManager : public AudioManagerBase {
86 public:
87 MockAudioManager() : AudioManagerBase(&fake_audio_log_factory_) {}
88 virtual ~MockAudioManager() {
89 Shutdown();
92 MOCK_METHOD0(HasAudioOutputDevices, bool());
93 MOCK_METHOD0(HasAudioInputDevices, bool());
94 MOCK_METHOD0(GetAudioInputDeviceModel, base::string16());
95 MOCK_METHOD2(MakeAudioOutputStream, AudioOutputStream*(
96 const AudioParameters& params,
97 const std::string& device_id));
98 MOCK_METHOD2(MakeAudioOutputStreamProxy, AudioOutputStream*(
99 const AudioParameters& params,
100 const std::string& device_id));
101 MOCK_METHOD2(MakeAudioInputStream, AudioInputStream*(
102 const AudioParameters& params, const std::string& device_id));
103 MOCK_METHOD0(ShowAudioInputSettings, void());
104 MOCK_METHOD0(GetTaskRunner, scoped_refptr<base::SingleThreadTaskRunner>());
105 MOCK_METHOD0(GetWorkerTaskRunner,
106 scoped_refptr<base::SingleThreadTaskRunner>());
107 MOCK_METHOD1(GetAudioInputDeviceNames, void(
108 media::AudioDeviceNames* device_name));
110 MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
111 const AudioParameters& params));
112 MOCK_METHOD2(MakeLowLatencyOutputStream, AudioOutputStream*(
113 const AudioParameters& params, const std::string& device_id));
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_METHOD2(GetPreferredOutputStreamParameters, AudioParameters(
119 const std::string& device_id, const AudioParameters& params));
121 private:
122 media::FakeAudioLogFactory fake_audio_log_factory_;
125 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
126 public:
127 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) {
128 audio_bus->Zero();
129 return audio_bus->frames();
131 MOCK_METHOD1(OnError, void(AudioOutputStream* stream));
134 } // namespace
136 namespace media {
138 class AudioOutputProxyTest : public testing::Test {
139 protected:
140 void SetUp() override {
141 EXPECT_CALL(manager_, GetTaskRunner())
142 .WillRepeatedly(Return(message_loop_.task_runner()));
143 EXPECT_CALL(manager_, GetWorkerTaskRunner())
144 .WillRepeatedly(Return(message_loop_.task_runner()));
145 // Use a low sample rate and large buffer size when testing otherwise the
146 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
147 // RunUntilIdle() will never terminate.
148 params_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR,
149 CHANNEL_LAYOUT_STEREO, 8000, 16, 2048);
150 InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs));
153 void TearDown() override {
154 // This is necessary to free all proxy objects that have been
155 // closed by the test.
156 message_loop_.RunUntilIdle();
159 virtual void InitDispatcher(base::TimeDelta close_delay) {
160 dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(),
161 params_,
162 std::string(),
163 close_delay);
166 virtual void OnStart() {}
168 MockAudioManager& manager() {
169 return manager_;
172 void WaitForCloseTimer(MockAudioOutputStream* stream) {
173 base::RunLoop run_loop;
174 EXPECT_CALL(*stream, Close())
175 .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
176 run_loop.Run();
179 void CloseAndWaitForCloseTimer(AudioOutputProxy* proxy,
180 MockAudioOutputStream* stream) {
181 // Close the stream and verify it doesn't happen immediately.
182 proxy->Close();
183 Mock::VerifyAndClear(stream);
185 // Wait for the actual close event to come from the close timer.
186 WaitForCloseTimer(stream);
189 // Basic Open() and Close() test.
190 void OpenAndClose(AudioOutputDispatcher* dispatcher) {
191 MockAudioOutputStream stream(&manager_, params_);
193 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
194 .WillOnce(Return(&stream));
195 EXPECT_CALL(stream, Open())
196 .WillOnce(Return(true));
198 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
199 EXPECT_TRUE(proxy->Open());
200 CloseAndWaitForCloseTimer(proxy, &stream);
203 // Creates a stream, and then calls Start() and Stop().
204 void StartAndStop(AudioOutputDispatcher* dispatcher) {
205 MockAudioOutputStream stream(&manager_, params_);
207 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
208 .WillOnce(Return(&stream));
209 EXPECT_CALL(stream, Open())
210 .WillOnce(Return(true));
211 EXPECT_CALL(stream, SetVolume(_))
212 .Times(1);
214 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
215 EXPECT_TRUE(proxy->Open());
217 proxy->Start(&callback_);
218 OnStart();
219 proxy->Stop();
221 CloseAndWaitForCloseTimer(proxy, &stream);
222 EXPECT_TRUE(stream.stop_called());
223 EXPECT_TRUE(stream.start_called());
226 // Verify that the stream is closed after Stop() is called.
227 void CloseAfterStop(AudioOutputDispatcher* dispatcher) {
228 MockAudioOutputStream stream(&manager_, params_);
230 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
231 .WillOnce(Return(&stream));
232 EXPECT_CALL(stream, Open())
233 .WillOnce(Return(true));
234 EXPECT_CALL(stream, SetVolume(_))
235 .Times(1);
237 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
238 EXPECT_TRUE(proxy->Open());
240 proxy->Start(&callback_);
241 OnStart();
242 proxy->Stop();
244 // Wait for the close timer to fire after StopStream().
245 WaitForCloseTimer(&stream);
246 proxy->Close();
247 EXPECT_TRUE(stream.stop_called());
248 EXPECT_TRUE(stream.start_called());
251 // Create two streams, but don't start them. Only one device must be opened.
252 void TwoStreams(AudioOutputDispatcher* dispatcher) {
253 MockAudioOutputStream stream(&manager_, params_);
255 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
256 .WillOnce(Return(&stream));
257 EXPECT_CALL(stream, Open())
258 .WillOnce(Return(true));
260 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
261 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
262 EXPECT_TRUE(proxy1->Open());
263 EXPECT_TRUE(proxy2->Open());
264 proxy1->Close();
265 CloseAndWaitForCloseTimer(proxy2, &stream);
266 EXPECT_FALSE(stream.stop_called());
267 EXPECT_FALSE(stream.start_called());
270 // Open() method failed.
271 void OpenFailed(AudioOutputDispatcher* dispatcher) {
272 MockAudioOutputStream stream(&manager_, params_);
274 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
275 .WillOnce(Return(&stream));
276 EXPECT_CALL(stream, Open())
277 .WillOnce(Return(false));
278 EXPECT_CALL(stream, Close())
279 .Times(1);
281 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
282 EXPECT_FALSE(proxy->Open());
283 proxy->Close();
284 EXPECT_FALSE(stream.stop_called());
285 EXPECT_FALSE(stream.start_called());
288 void CreateAndWait(AudioOutputDispatcher* dispatcher) {
289 MockAudioOutputStream stream(&manager_, params_);
291 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
292 .WillOnce(Return(&stream));
293 EXPECT_CALL(stream, Open())
294 .WillOnce(Return(true));
296 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
297 EXPECT_TRUE(proxy->Open());
299 WaitForCloseTimer(&stream);
300 proxy->Close();
301 EXPECT_FALSE(stream.stop_called());
302 EXPECT_FALSE(stream.start_called());
305 void OneStream_TwoPlays(AudioOutputDispatcher* dispatcher) {
306 MockAudioOutputStream stream(&manager_, params_);
308 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
309 .WillOnce(Return(&stream));
311 EXPECT_CALL(stream, Open())
312 .WillOnce(Return(true));
313 EXPECT_CALL(stream, SetVolume(_))
314 .Times(2);
316 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
317 EXPECT_TRUE(proxy1->Open());
319 proxy1->Start(&callback_);
320 OnStart();
321 proxy1->Stop();
323 // The stream should now be idle and get reused by |proxy2|.
324 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
325 EXPECT_TRUE(proxy2->Open());
326 proxy2->Start(&callback_);
327 OnStart();
328 proxy2->Stop();
330 proxy1->Close();
331 CloseAndWaitForCloseTimer(proxy2, &stream);
332 EXPECT_TRUE(stream.stop_called());
333 EXPECT_TRUE(stream.start_called());
336 void TwoStreams_BothPlaying(AudioOutputDispatcher* dispatcher) {
337 MockAudioOutputStream stream1(&manager_, params_);
338 MockAudioOutputStream stream2(&manager_, params_);
340 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
341 .WillOnce(Return(&stream1))
342 .WillOnce(Return(&stream2));
344 EXPECT_CALL(stream1, Open())
345 .WillOnce(Return(true));
346 EXPECT_CALL(stream1, SetVolume(_))
347 .Times(1);
349 EXPECT_CALL(stream2, Open())
350 .WillOnce(Return(true));
351 EXPECT_CALL(stream2, SetVolume(_))
352 .Times(1);
354 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
355 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
356 EXPECT_TRUE(proxy1->Open());
357 EXPECT_TRUE(proxy2->Open());
359 proxy1->Start(&callback_);
360 proxy2->Start(&callback_);
361 OnStart();
362 proxy1->Stop();
363 CloseAndWaitForCloseTimer(proxy1, &stream1);
365 proxy2->Stop();
366 CloseAndWaitForCloseTimer(proxy2, &stream2);
368 EXPECT_TRUE(stream1.stop_called());
369 EXPECT_TRUE(stream1.start_called());
370 EXPECT_TRUE(stream2.stop_called());
371 EXPECT_TRUE(stream2.start_called());
374 void StartFailed(AudioOutputDispatcher* dispatcher) {
375 MockAudioOutputStream stream(&manager_, params_);
377 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
378 .WillOnce(Return(&stream));
379 EXPECT_CALL(stream, Open())
380 .WillOnce(Return(true));
382 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
383 EXPECT_TRUE(proxy->Open());
385 WaitForCloseTimer(&stream);
387 // |stream| is closed at this point. Start() should reopen it again.
388 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
389 .Times(2)
390 .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream*>(NULL)));
392 EXPECT_CALL(callback_, OnError(_))
393 .Times(2);
395 proxy->Start(&callback_);
397 // Double Start() in the error case should be allowed since it's possible a
398 // callback may not have had time to process the OnError() in between.
399 proxy->Stop();
400 proxy->Start(&callback_);
402 Mock::VerifyAndClear(&callback_);
404 proxy->Close();
407 base::MessageLoop message_loop_;
408 scoped_refptr<AudioOutputDispatcherImpl> dispatcher_impl_;
409 MockAudioManager manager_;
410 MockAudioSourceCallback callback_;
411 AudioParameters params_;
414 class AudioOutputResamplerTest : public AudioOutputProxyTest {
415 public:
416 void TearDown() override { AudioOutputProxyTest::TearDown(); }
418 void InitDispatcher(base::TimeDelta close_delay) override {
419 // Use a low sample rate and large buffer size when testing otherwise the
420 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
421 // RunUntilIdle() will never terminate.
422 resampler_params_ = AudioParameters(
423 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
424 16000, 16, 1024);
425 resampler_ = new AudioOutputResampler(
426 &manager(), params_, resampler_params_, std::string(), close_delay);
429 void OnStart() override {
430 // Let Start() run for a bit.
431 base::RunLoop run_loop;
432 message_loop_.PostDelayedTask(
433 FROM_HERE,
434 run_loop.QuitClosure(),
435 base::TimeDelta::FromMilliseconds(kStartRunTimeMs));
436 run_loop.Run();
439 protected:
440 AudioParameters resampler_params_;
441 scoped_refptr<AudioOutputResampler> resampler_;
444 TEST_F(AudioOutputProxyTest, CreateAndClose) {
445 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_.get());
446 proxy->Close();
449 TEST_F(AudioOutputResamplerTest, CreateAndClose) {
450 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get());
451 proxy->Close();
454 TEST_F(AudioOutputProxyTest, OpenAndClose) {
455 OpenAndClose(dispatcher_impl_.get());
458 TEST_F(AudioOutputResamplerTest, OpenAndClose) {
459 OpenAndClose(resampler_.get());
462 // Create a stream, and verify that it is closed after kTestCloseDelayMs.
463 // if it doesn't start playing.
464 TEST_F(AudioOutputProxyTest, CreateAndWait) {
465 CreateAndWait(dispatcher_impl_.get());
468 // Create a stream, and verify that it is closed after kTestCloseDelayMs.
469 // if it doesn't start playing.
470 TEST_F(AudioOutputResamplerTest, CreateAndWait) {
471 CreateAndWait(resampler_.get());
474 TEST_F(AudioOutputProxyTest, StartAndStop) {
475 StartAndStop(dispatcher_impl_.get());
478 TEST_F(AudioOutputResamplerTest, StartAndStop) {
479 StartAndStop(resampler_.get());
482 TEST_F(AudioOutputProxyTest, CloseAfterStop) {
483 CloseAfterStop(dispatcher_impl_.get());
486 TEST_F(AudioOutputResamplerTest, CloseAfterStop) {
487 CloseAfterStop(resampler_.get());
490 TEST_F(AudioOutputProxyTest, TwoStreams) {
491 TwoStreams(dispatcher_impl_.get());
494 TEST_F(AudioOutputResamplerTest, TwoStreams) {
495 TwoStreams(resampler_.get());
498 // Two streams: verify that second stream is allocated when the first
499 // starts playing.
500 TEST_F(AudioOutputProxyTest, OneStream_TwoPlays) {
501 OneStream_TwoPlays(dispatcher_impl_.get());
504 TEST_F(AudioOutputResamplerTest, OneStream_TwoPlays) {
505 OneStream_TwoPlays(resampler_.get());
508 // Two streams, both are playing. Dispatcher should not open a third stream.
509 TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
510 TwoStreams_BothPlaying(dispatcher_impl_.get());
513 TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) {
514 TwoStreams_BothPlaying(resampler_.get());
517 TEST_F(AudioOutputProxyTest, OpenFailed) {
518 OpenFailed(dispatcher_impl_.get());
521 // Start() method failed.
522 TEST_F(AudioOutputProxyTest, StartFailed) {
523 StartFailed(dispatcher_impl_.get());
526 TEST_F(AudioOutputResamplerTest, StartFailed) {
527 StartFailed(resampler_.get());
530 // Simulate AudioOutputStream::Create() failure with a low latency stream and
531 // ensure AudioOutputResampler falls back to the high latency path.
532 TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) {
533 MockAudioOutputStream stream(&manager_, params_);
534 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
535 .Times(2)
536 .WillOnce(Return(static_cast<AudioOutputStream*>(NULL)))
537 .WillRepeatedly(Return(&stream));
538 EXPECT_CALL(stream, Open())
539 .WillOnce(Return(true));
541 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get());
542 EXPECT_TRUE(proxy->Open());
543 CloseAndWaitForCloseTimer(proxy, &stream);
546 // Simulate AudioOutputStream::Open() failure with a low latency stream and
547 // ensure AudioOutputResampler falls back to the high latency path.
548 TEST_F(AudioOutputResamplerTest, LowLatencyOpenFailedFallback) {
549 MockAudioOutputStream failed_stream(&manager_, params_);
550 MockAudioOutputStream okay_stream(&manager_, params_);
551 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
552 .Times(2)
553 .WillOnce(Return(&failed_stream))
554 .WillRepeatedly(Return(&okay_stream));
555 EXPECT_CALL(failed_stream, Open())
556 .WillOnce(Return(false));
557 EXPECT_CALL(failed_stream, Close())
558 .Times(1);
559 EXPECT_CALL(okay_stream, Open())
560 .WillOnce(Return(true));
562 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get());
563 EXPECT_TRUE(proxy->Open());
564 CloseAndWaitForCloseTimer(proxy, &okay_stream);
567 // Simulate failures to open both the low latency and the fallback high latency
568 // stream and ensure AudioOutputResampler falls back to a fake stream.
569 TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) {
570 MockAudioOutputStream okay_stream(&manager_, params_);
572 // Only Windows has a high latency output driver that is not the same as the low
573 // latency path.
574 #if defined(OS_WIN)
575 static const int kFallbackCount = 2;
576 #else
577 static const int kFallbackCount = 1;
578 #endif
579 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
580 .Times(kFallbackCount)
581 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
583 // To prevent shared memory issues the sample rate and buffer size should
584 // match the input stream parameters.
585 EXPECT_CALL(manager(), MakeAudioOutputStream(AllOf(
586 testing::Property(&AudioParameters::format, AudioParameters::AUDIO_FAKE),
587 testing::Property(&AudioParameters::sample_rate, params_.sample_rate()),
588 testing::Property(
589 &AudioParameters::frames_per_buffer, params_.frames_per_buffer())),
591 .Times(1)
592 .WillOnce(Return(&okay_stream));
593 EXPECT_CALL(okay_stream, Open())
594 .WillOnce(Return(true));
596 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get());
597 EXPECT_TRUE(proxy->Open());
598 CloseAndWaitForCloseTimer(proxy, &okay_stream);
601 // Simulate failures to open both the low latency, the fallback high latency
602 // stream, and the fake audio output stream and ensure AudioOutputResampler
603 // terminates normally.
604 TEST_F(AudioOutputResamplerTest, AllFallbackFailed) {
605 // Only Windows has a high latency output driver that is not the same as the low
606 // latency path.
607 #if defined(OS_WIN)
608 static const int kFallbackCount = 3;
609 #else
610 static const int kFallbackCount = 2;
611 #endif
612 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
613 .Times(kFallbackCount)
614 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
616 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get());
617 EXPECT_FALSE(proxy->Open());
618 proxy->Close();
621 // Simulate an eventual OpenStream() failure; i.e. successful OpenStream() calls
622 // eventually followed by one which fails; root cause of http://crbug.com/150619
623 TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) {
624 MockAudioOutputStream stream1(&manager_, params_);
625 MockAudioOutputStream stream2(&manager_, params_);
627 // Setup the mock such that all three streams are successfully created.
628 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
629 .WillOnce(Return(&stream1))
630 .WillOnce(Return(&stream2))
631 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
633 // Stream1 should be able to successfully open and start.
634 EXPECT_CALL(stream1, Open())
635 .WillOnce(Return(true));
636 EXPECT_CALL(stream1, SetVolume(_))
637 .Times(1);
639 // Stream2 should also be able to successfully open and start.
640 EXPECT_CALL(stream2, Open())
641 .WillOnce(Return(true));
642 EXPECT_CALL(stream2, SetVolume(_))
643 .Times(1);
645 // Open and start the first proxy and stream.
646 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_.get());
647 EXPECT_TRUE(proxy1->Open());
648 proxy1->Start(&callback_);
649 OnStart();
651 // Open and start the second proxy and stream.
652 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get());
653 EXPECT_TRUE(proxy2->Open());
654 proxy2->Start(&callback_);
655 OnStart();
657 // Attempt to open the third stream which should fail.
658 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get());
659 EXPECT_FALSE(proxy3->Open());
660 proxy3->Close();
662 // Perform the required Stop()/Close() shutdown dance for each proxy. Under
663 // the hood each proxy should correctly call CloseStream() if OpenStream()
664 // succeeded or not.
665 proxy2->Stop();
666 CloseAndWaitForCloseTimer(proxy2, &stream2);
668 proxy1->Stop();
669 CloseAndWaitForCloseTimer(proxy1, &stream1);
671 EXPECT_TRUE(stream1.stop_called());
672 EXPECT_TRUE(stream1.start_called());
673 EXPECT_TRUE(stream2.stop_called());
674 EXPECT_TRUE(stream2.start_called());
677 // Simulate failures to open both the low latency and the fallback high latency
678 // stream and ensure AudioOutputResampler falls back to a fake stream. Ensure
679 // that after the close delay elapses, opening another stream succeeds with a
680 // non-fake stream.
681 TEST_F(AudioOutputResamplerTest, FallbackRecovery) {
682 MockAudioOutputStream fake_stream(&manager_, params_);
684 // Trigger the fallback mechanism until a fake output stream is created.
685 #if defined(OS_WIN)
686 static const int kFallbackCount = 2;
687 #else
688 static const int kFallbackCount = 1;
689 #endif
690 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
691 .Times(kFallbackCount)
692 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
693 EXPECT_CALL(manager(),
694 MakeAudioOutputStream(
695 AllOf(testing::Property(&AudioParameters::format,
696 AudioParameters::AUDIO_FAKE),
697 testing::Property(&AudioParameters::sample_rate,
698 params_.sample_rate()),
699 testing::Property(&AudioParameters::frames_per_buffer,
700 params_.frames_per_buffer())),
701 _)).WillOnce(Return(&fake_stream));
702 EXPECT_CALL(fake_stream, Open()).WillOnce(Return(true));
703 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get());
704 EXPECT_TRUE(proxy->Open());
705 CloseAndWaitForCloseTimer(proxy, &fake_stream);
707 // Once all proxies have been closed, AudioOutputResampler will start the
708 // reinitialization timer and execute it after the close delay elapses.
709 base::RunLoop run_loop;
710 message_loop_.PostDelayedTask(
711 FROM_HERE, run_loop.QuitClosure(),
712 base::TimeDelta::FromMilliseconds(2 * kTestCloseDelayMs));
713 run_loop.Run();
715 // Verify a non-fake stream can be created.
716 MockAudioOutputStream real_stream(&manager_, params_);
717 EXPECT_CALL(manager(),
718 MakeAudioOutputStream(
719 testing::Property(&AudioParameters::format,
720 testing::Ne(AudioParameters::AUDIO_FAKE)),
721 _)).WillOnce(Return(&real_stream));
723 // Stream1 should be able to successfully open and start.
724 EXPECT_CALL(real_stream, Open()).WillOnce(Return(true));
725 proxy = new AudioOutputProxy(resampler_.get());
726 EXPECT_TRUE(proxy->Open());
727 CloseAndWaitForCloseTimer(proxy, &real_stream);
730 } // namespace media