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.
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"
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
;
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
{
49 MockAudioOutputStream(AudioManagerBase
* manager
,
50 const AudioParameters
& params
)
51 : start_called_(false),
55 FakeAudioOutputStream::MakeFakeStream(manager
, params_
)) {
58 void Start(AudioSourceCallback
* callback
) {
60 fake_output_stream_
->Start(callback
);
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());
81 AudioParameters params_
;
82 scoped_ptr
<AudioOutputStream
> fake_output_stream_
;
85 class MockAudioManager
: public AudioManagerBase
{
87 MockAudioManager() : AudioManagerBase(&fake_audio_log_factory_
) {}
88 virtual ~MockAudioManager() {
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
));
122 media::FakeAudioLogFactory fake_audio_log_factory_
;
125 class MockAudioSourceCallback
: public AudioOutputStream::AudioSourceCallback
{
127 int OnMoreData(AudioBus
* audio_bus
, uint32 total_bytes_delay
) {
129 return audio_bus
->frames();
131 MOCK_METHOD1(OnError
, void(AudioOutputStream
* stream
));
138 class AudioOutputProxyTest
: public testing::Test
{
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(),
166 virtual void OnStart() {}
168 MockAudioManager
& 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
));
179 void CloseAndWaitForCloseTimer(AudioOutputProxy
* proxy
,
180 MockAudioOutputStream
* stream
) {
181 // Close the stream and verify it doesn't happen immediately.
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(_
))
214 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
215 EXPECT_TRUE(proxy
->Open());
217 proxy
->Start(&callback_
);
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(_
))
237 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
238 EXPECT_TRUE(proxy
->Open());
240 proxy
->Start(&callback_
);
244 // Wait for the close timer to fire after StopStream().
245 WaitForCloseTimer(&stream
);
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());
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())
281 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
282 EXPECT_FALSE(proxy
->Open());
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
);
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(_
))
316 AudioOutputProxy
* proxy1
= new AudioOutputProxy(dispatcher
);
317 EXPECT_TRUE(proxy1
->Open());
319 proxy1
->Start(&callback_
);
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_
);
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(_
))
349 EXPECT_CALL(stream2
, Open())
350 .WillOnce(Return(true));
351 EXPECT_CALL(stream2
, SetVolume(_
))
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_
);
363 CloseAndWaitForCloseTimer(proxy1
, &stream1
);
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(_
, _
))
390 .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream
*>(NULL
)));
392 EXPECT_CALL(callback_
, OnError(_
))
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.
400 proxy
->Start(&callback_
);
402 Mock::VerifyAndClear(&callback_
);
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
{
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
,
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(
434 run_loop
.QuitClosure(),
435 base::TimeDelta::FromMilliseconds(kStartRunTimeMs
));
440 AudioParameters resampler_params_
;
441 scoped_refptr
<AudioOutputResampler
> resampler_
;
444 TEST_F(AudioOutputProxyTest
, CreateAndClose
) {
445 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher_impl_
.get());
449 TEST_F(AudioOutputResamplerTest
, CreateAndClose
) {
450 AudioOutputProxy
* proxy
= new AudioOutputProxy(resampler_
.get());
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
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(_
, _
))
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(_
, _
))
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())
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
575 static const int kFallbackCount
= 2;
577 static const int kFallbackCount
= 1;
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()),
589 &AudioParameters::frames_per_buffer
, params_
.frames_per_buffer())),
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
608 static const int kFallbackCount
= 3;
610 static const int kFallbackCount
= 2;
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());
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(_
))
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(_
))
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_
);
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_
);
657 // Attempt to open the third stream which should fail.
658 AudioOutputProxy
* proxy3
= new AudioOutputProxy(resampler_
.get());
659 EXPECT_FALSE(proxy3
->Open());
662 // Perform the required Stop()/Close() shutdown dance for each proxy. Under
663 // the hood each proxy should correctly call CloseStream() if OpenStream()
666 CloseAndWaitForCloseTimer(proxy2
, &stream2
);
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
681 TEST_F(AudioOutputResamplerTest
, FallbackRecovery
) {
682 MockAudioOutputStream
fake_stream(&manager_
, params_
);
684 // Trigger the fallback mechanism until a fake output stream is created.
686 static const int kFallbackCount
= 2;
688 static const int kFallbackCount
= 1;
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
));
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
);