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::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;
40 static const int kTestCloseDelayMs = 10;
42 // Delay between callbacks to AudioSourceCallback::OnMoreData.
43 static const int kOnMoreDataCallbackDelayMs = 10;
45 // Let start run long enough for many OnMoreData callbacks to occur.
46 static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10;
48 class MockAudioOutputStream : public AudioOutputStream {
50 MockAudioOutputStream(AudioManagerBase* manager,
51 const AudioParameters& params)
52 : start_called_(false),
56 FakeAudioOutputStream::MakeFakeStream(manager, params_)) {
59 void Start(AudioSourceCallback* callback) {
61 fake_output_stream_->Start(callback);
66 fake_output_stream_->Stop();
69 ~MockAudioOutputStream() {}
71 bool start_called() { return start_called_; }
72 bool stop_called() { return stop_called_; }
74 MOCK_METHOD0(Open, bool());
75 MOCK_METHOD1(SetVolume, void(double volume));
76 MOCK_METHOD1(GetVolume, void(double* volume));
77 MOCK_METHOD0(Close, void());
82 AudioParameters params_;
83 scoped_ptr<AudioOutputStream> fake_output_stream_;
86 class MockAudioManager : public AudioManagerBase {
88 MockAudioManager() : AudioManagerBase(&fake_audio_log_factory_) {}
89 virtual ~MockAudioManager() {
93 MOCK_METHOD0(HasAudioOutputDevices, bool());
94 MOCK_METHOD0(HasAudioInputDevices, bool());
95 MOCK_METHOD0(GetAudioInputDeviceModel, base::string16());
96 MOCK_METHOD3(MakeAudioOutputStream, AudioOutputStream*(
97 const AudioParameters& params,
98 const std::string& device_id,
99 const std::string& input_device_id));
100 MOCK_METHOD3(MakeAudioOutputStreamProxy, AudioOutputStream*(
101 const AudioParameters& params,
102 const std::string& device_id,
103 const std::string& input_device_id));
104 MOCK_METHOD2(MakeAudioInputStream, AudioInputStream*(
105 const AudioParameters& params, const std::string& device_id));
106 MOCK_METHOD0(ShowAudioInputSettings, void());
107 MOCK_METHOD0(GetTaskRunner, scoped_refptr<base::SingleThreadTaskRunner>());
108 MOCK_METHOD0(GetWorkerTaskRunner,
109 scoped_refptr<base::SingleThreadTaskRunner>());
110 MOCK_METHOD1(GetAudioInputDeviceNames, void(
111 media::AudioDeviceNames* device_name));
113 MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
114 const AudioParameters& params));
115 MOCK_METHOD3(MakeLowLatencyOutputStream, AudioOutputStream*(
116 const AudioParameters& params, const std::string& device_id,
117 const std::string& input_device_id));
118 MOCK_METHOD2(MakeLinearInputStream, AudioInputStream*(
119 const AudioParameters& params, const std::string& device_id));
120 MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
121 const AudioParameters& params, const std::string& device_id));
122 MOCK_METHOD2(GetPreferredOutputStreamParameters, AudioParameters(
123 const std::string& device_id, const AudioParameters& params));
126 media::FakeAudioLogFactory fake_audio_log_factory_;
129 class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
131 int OnMoreData(AudioBus* audio_bus, AudioBuffersState buffers_state) {
133 return audio_bus->frames();
135 int OnMoreIOData(AudioBus* source, AudioBus* dest,
136 AudioBuffersState buffers_state) {
137 return OnMoreData(dest, buffers_state);
139 MOCK_METHOD1(OnError, void(AudioOutputStream* stream));
146 class AudioOutputProxyTest : public testing::Test {
148 virtual void SetUp() {
149 EXPECT_CALL(manager_, GetTaskRunner())
150 .WillRepeatedly(Return(message_loop_.message_loop_proxy()));
151 EXPECT_CALL(manager_, GetWorkerTaskRunner())
152 .WillRepeatedly(Return(message_loop_.message_loop_proxy()));
153 // Use a low sample rate and large buffer size when testing otherwise the
154 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
155 // RunUntilIdle() will never terminate.
156 params_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR,
157 CHANNEL_LAYOUT_STEREO, 8000, 16, 2048);
158 InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs));
161 virtual void TearDown() {
162 // This is necessary to free all proxy objects that have been
163 // closed by the test.
164 message_loop_.RunUntilIdle();
167 virtual void InitDispatcher(base::TimeDelta close_delay) {
168 dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(),
175 virtual void OnStart() {}
177 MockAudioManager& manager() {
181 void WaitForCloseTimer(MockAudioOutputStream* stream) {
182 base::RunLoop run_loop;
183 EXPECT_CALL(*stream, Close())
184 .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
188 void CloseAndWaitForCloseTimer(AudioOutputProxy* proxy,
189 MockAudioOutputStream* stream) {
190 // Close the stream and verify it doesn't happen immediately.
192 Mock::VerifyAndClear(stream);
194 // Wait for the actual close event to come from the close timer.
195 WaitForCloseTimer(stream);
198 // Basic Open() and Close() test.
199 void OpenAndClose(AudioOutputDispatcher* dispatcher) {
200 MockAudioOutputStream stream(&manager_, params_);
202 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
203 .WillOnce(Return(&stream));
204 EXPECT_CALL(stream, Open())
205 .WillOnce(Return(true));
207 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
208 EXPECT_TRUE(proxy->Open());
209 CloseAndWaitForCloseTimer(proxy, &stream);
212 // Creates a stream, and then calls Start() and Stop().
213 void StartAndStop(AudioOutputDispatcher* dispatcher) {
214 MockAudioOutputStream stream(&manager_, params_);
216 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
217 .WillOnce(Return(&stream));
218 EXPECT_CALL(stream, Open())
219 .WillOnce(Return(true));
220 EXPECT_CALL(stream, SetVolume(_))
223 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
224 EXPECT_TRUE(proxy->Open());
226 proxy->Start(&callback_);
230 CloseAndWaitForCloseTimer(proxy, &stream);
231 EXPECT_TRUE(stream.stop_called());
232 EXPECT_TRUE(stream.start_called());
235 // Verify that the stream is closed after Stop() is called.
236 void CloseAfterStop(AudioOutputDispatcher* dispatcher) {
237 MockAudioOutputStream stream(&manager_, params_);
239 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
240 .WillOnce(Return(&stream));
241 EXPECT_CALL(stream, Open())
242 .WillOnce(Return(true));
243 EXPECT_CALL(stream, SetVolume(_))
246 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
247 EXPECT_TRUE(proxy->Open());
249 proxy->Start(&callback_);
253 // Wait for the close timer to fire after StopStream().
254 WaitForCloseTimer(&stream);
256 EXPECT_TRUE(stream.stop_called());
257 EXPECT_TRUE(stream.start_called());
260 // Create two streams, but don't start them. Only one device must be opened.
261 void TwoStreams(AudioOutputDispatcher* dispatcher) {
262 MockAudioOutputStream stream(&manager_, params_);
264 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
265 .WillOnce(Return(&stream));
266 EXPECT_CALL(stream, Open())
267 .WillOnce(Return(true));
269 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
270 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
271 EXPECT_TRUE(proxy1->Open());
272 EXPECT_TRUE(proxy2->Open());
274 CloseAndWaitForCloseTimer(proxy2, &stream);
275 EXPECT_FALSE(stream.stop_called());
276 EXPECT_FALSE(stream.start_called());
279 // Open() method failed.
280 void OpenFailed(AudioOutputDispatcher* dispatcher) {
281 MockAudioOutputStream stream(&manager_, params_);
283 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
284 .WillOnce(Return(&stream));
285 EXPECT_CALL(stream, Open())
286 .WillOnce(Return(false));
287 EXPECT_CALL(stream, Close())
290 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
291 EXPECT_FALSE(proxy->Open());
293 EXPECT_FALSE(stream.stop_called());
294 EXPECT_FALSE(stream.start_called());
297 void CreateAndWait(AudioOutputDispatcher* dispatcher) {
298 MockAudioOutputStream stream(&manager_, params_);
300 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
301 .WillOnce(Return(&stream));
302 EXPECT_CALL(stream, Open())
303 .WillOnce(Return(true));
305 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
306 EXPECT_TRUE(proxy->Open());
308 WaitForCloseTimer(&stream);
310 EXPECT_FALSE(stream.stop_called());
311 EXPECT_FALSE(stream.start_called());
314 void OneStream_TwoPlays(AudioOutputDispatcher* dispatcher) {
315 MockAudioOutputStream stream(&manager_, params_);
317 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
318 .WillOnce(Return(&stream));
320 EXPECT_CALL(stream, Open())
321 .WillOnce(Return(true));
322 EXPECT_CALL(stream, SetVolume(_))
325 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
326 EXPECT_TRUE(proxy1->Open());
328 proxy1->Start(&callback_);
332 // The stream should now be idle and get reused by |proxy2|.
333 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
334 EXPECT_TRUE(proxy2->Open());
335 proxy2->Start(&callback_);
340 CloseAndWaitForCloseTimer(proxy2, &stream);
341 EXPECT_TRUE(stream.stop_called());
342 EXPECT_TRUE(stream.start_called());
345 void TwoStreams_BothPlaying(AudioOutputDispatcher* dispatcher) {
346 MockAudioOutputStream stream1(&manager_, params_);
347 MockAudioOutputStream stream2(&manager_, params_);
349 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
350 .WillOnce(Return(&stream1))
351 .WillOnce(Return(&stream2));
353 EXPECT_CALL(stream1, Open())
354 .WillOnce(Return(true));
355 EXPECT_CALL(stream1, SetVolume(_))
358 EXPECT_CALL(stream2, Open())
359 .WillOnce(Return(true));
360 EXPECT_CALL(stream2, SetVolume(_))
363 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
364 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
365 EXPECT_TRUE(proxy1->Open());
366 EXPECT_TRUE(proxy2->Open());
368 proxy1->Start(&callback_);
369 proxy2->Start(&callback_);
372 CloseAndWaitForCloseTimer(proxy1, &stream1);
375 CloseAndWaitForCloseTimer(proxy2, &stream2);
377 EXPECT_TRUE(stream1.stop_called());
378 EXPECT_TRUE(stream1.start_called());
379 EXPECT_TRUE(stream2.stop_called());
380 EXPECT_TRUE(stream2.start_called());
383 void StartFailed(AudioOutputDispatcher* dispatcher) {
384 MockAudioOutputStream stream(&manager_, params_);
386 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
387 .WillOnce(Return(&stream));
388 EXPECT_CALL(stream, Open())
389 .WillOnce(Return(true));
391 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
392 EXPECT_TRUE(proxy->Open());
394 WaitForCloseTimer(&stream);
396 // |stream| is closed at this point. Start() should reopen it again.
397 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
399 .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream*>(NULL)));
401 EXPECT_CALL(callback_, OnError(_))
404 proxy->Start(&callback_);
406 // Double Start() in the error case should be allowed since it's possible a
407 // callback may not have had time to process the OnError() in between.
409 proxy->Start(&callback_);
411 Mock::VerifyAndClear(&callback_);
416 base::MessageLoop message_loop_;
417 scoped_refptr<AudioOutputDispatcherImpl> dispatcher_impl_;
418 MockAudioManager manager_;
419 MockAudioSourceCallback callback_;
420 AudioParameters params_;
423 class AudioOutputResamplerTest : public AudioOutputProxyTest {
425 virtual void TearDown() {
426 AudioOutputProxyTest::TearDown();
429 virtual void InitDispatcher(base::TimeDelta close_delay) OVERRIDE {
430 // Use a low sample rate and large buffer size when testing otherwise the
431 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
432 // RunUntilIdle() will never terminate.
433 resampler_params_ = AudioParameters(
434 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
436 resampler_ = new AudioOutputResampler(
437 &manager(), params_, resampler_params_, std::string(), std::string(),
441 virtual void OnStart() OVERRIDE {
442 // Let Start() run for a bit.
443 base::RunLoop run_loop;
444 message_loop_.PostDelayedTask(
446 run_loop.QuitClosure(),
447 base::TimeDelta::FromMilliseconds(kStartRunTimeMs));
452 AudioParameters resampler_params_;
453 scoped_refptr<AudioOutputResampler> resampler_;
456 TEST_F(AudioOutputProxyTest, CreateAndClose) {
457 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_);
461 TEST_F(AudioOutputResamplerTest, CreateAndClose) {
462 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
466 TEST_F(AudioOutputProxyTest, OpenAndClose) {
467 OpenAndClose(dispatcher_impl_);
470 TEST_F(AudioOutputResamplerTest, OpenAndClose) {
471 OpenAndClose(resampler_);
474 // Create a stream, and verify that it is closed after kTestCloseDelayMs.
475 // if it doesn't start playing.
476 TEST_F(AudioOutputProxyTest, CreateAndWait) {
477 CreateAndWait(dispatcher_impl_);
480 // Create a stream, and verify that it is closed after kTestCloseDelayMs.
481 // if it doesn't start playing.
482 TEST_F(AudioOutputResamplerTest, CreateAndWait) {
483 CreateAndWait(resampler_);
486 TEST_F(AudioOutputProxyTest, StartAndStop) {
487 StartAndStop(dispatcher_impl_);
490 TEST_F(AudioOutputResamplerTest, StartAndStop) {
491 StartAndStop(resampler_);
494 TEST_F(AudioOutputProxyTest, CloseAfterStop) {
495 CloseAfterStop(dispatcher_impl_);
498 TEST_F(AudioOutputResamplerTest, CloseAfterStop) {
499 CloseAfterStop(resampler_);
502 TEST_F(AudioOutputProxyTest, TwoStreams) { TwoStreams(dispatcher_impl_); }
504 TEST_F(AudioOutputResamplerTest, TwoStreams) { TwoStreams(resampler_); }
506 // Two streams: verify that second stream is allocated when the first
508 TEST_F(AudioOutputProxyTest, OneStream_TwoPlays) {
509 OneStream_TwoPlays(dispatcher_impl_);
512 TEST_F(AudioOutputResamplerTest, OneStream_TwoPlays) {
513 OneStream_TwoPlays(resampler_);
516 // Two streams, both are playing. Dispatcher should not open a third stream.
517 TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
518 TwoStreams_BothPlaying(dispatcher_impl_);
521 TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) {
522 TwoStreams_BothPlaying(resampler_);
525 TEST_F(AudioOutputProxyTest, OpenFailed) { OpenFailed(dispatcher_impl_); }
527 // Start() method failed.
528 TEST_F(AudioOutputProxyTest, StartFailed) {
529 StartFailed(dispatcher_impl_);
532 TEST_F(AudioOutputResamplerTest, StartFailed) { StartFailed(resampler_); }
534 // Simulate AudioOutputStream::Create() failure with a low latency stream and
535 // ensure AudioOutputResampler falls back to the high latency path.
536 TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) {
537 MockAudioOutputStream stream(&manager_, params_);
538 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
540 .WillOnce(Return(static_cast<AudioOutputStream*>(NULL)))
541 .WillRepeatedly(Return(&stream));
542 EXPECT_CALL(stream, Open())
543 .WillOnce(Return(true));
545 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
546 EXPECT_TRUE(proxy->Open());
547 CloseAndWaitForCloseTimer(proxy, &stream);
550 // Simulate AudioOutputStream::Open() failure with a low latency stream and
551 // ensure AudioOutputResampler falls back to the high latency path.
552 TEST_F(AudioOutputResamplerTest, LowLatencyOpenFailedFallback) {
553 MockAudioOutputStream failed_stream(&manager_, params_);
554 MockAudioOutputStream okay_stream(&manager_, params_);
555 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
557 .WillOnce(Return(&failed_stream))
558 .WillRepeatedly(Return(&okay_stream));
559 EXPECT_CALL(failed_stream, Open())
560 .WillOnce(Return(false));
561 EXPECT_CALL(failed_stream, Close())
563 EXPECT_CALL(okay_stream, Open())
564 .WillOnce(Return(true));
566 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
567 EXPECT_TRUE(proxy->Open());
568 CloseAndWaitForCloseTimer(proxy, &okay_stream);
571 // Simulate failures to open both the low latency and the fallback high latency
572 // stream and ensure AudioOutputResampler falls back to a fake stream.
573 TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) {
574 MockAudioOutputStream okay_stream(&manager_, params_);
576 // Only Windows has a high latency output driver that is not the same as the low
579 static const int kFallbackCount = 2;
581 static const int kFallbackCount = 1;
583 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
584 .Times(kFallbackCount)
585 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
587 // To prevent shared memory issues the sample rate and buffer size should
588 // match the input stream parameters.
589 EXPECT_CALL(manager(), MakeAudioOutputStream(AllOf(
590 testing::Property(&AudioParameters::format, AudioParameters::AUDIO_FAKE),
591 testing::Property(&AudioParameters::sample_rate, params_.sample_rate()),
593 &AudioParameters::frames_per_buffer, params_.frames_per_buffer())),
596 .WillOnce(Return(&okay_stream));
597 EXPECT_CALL(okay_stream, Open())
598 .WillOnce(Return(true));
600 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
601 EXPECT_TRUE(proxy->Open());
602 CloseAndWaitForCloseTimer(proxy, &okay_stream);
605 // Simulate failures to open both the low latency, the fallback high latency
606 // stream, and the fake audio output stream and ensure AudioOutputResampler
607 // terminates normally.
608 TEST_F(AudioOutputResamplerTest, AllFallbackFailed) {
609 // Only Windows has a high latency output driver that is not the same as the low
612 static const int kFallbackCount = 3;
614 static const int kFallbackCount = 2;
616 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
617 .Times(kFallbackCount)
618 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
620 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_);
621 EXPECT_FALSE(proxy->Open());
625 // Simulate an eventual OpenStream() failure; i.e. successful OpenStream() calls
626 // eventually followed by one which fails; root cause of http://crbug.com/150619
627 TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) {
628 MockAudioOutputStream stream1(&manager_, params_);
629 MockAudioOutputStream stream2(&manager_, params_);
631 // Setup the mock such that all three streams are successfully created.
632 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
633 .WillOnce(Return(&stream1))
634 .WillOnce(Return(&stream2))
635 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
637 // Stream1 should be able to successfully open and start.
638 EXPECT_CALL(stream1, Open())
639 .WillOnce(Return(true));
640 EXPECT_CALL(stream1, SetVolume(_))
643 // Stream2 should also be able to successfully open and start.
644 EXPECT_CALL(stream2, Open())
645 .WillOnce(Return(true));
646 EXPECT_CALL(stream2, SetVolume(_))
649 // Open and start the first proxy and stream.
650 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_);
651 EXPECT_TRUE(proxy1->Open());
652 proxy1->Start(&callback_);
655 // Open and start the second proxy and stream.
656 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_);
657 EXPECT_TRUE(proxy2->Open());
658 proxy2->Start(&callback_);
661 // Attempt to open the third stream which should fail.
662 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_);
663 EXPECT_FALSE(proxy3->Open());
666 // Perform the required Stop()/Close() shutdown dance for each proxy. Under
667 // the hood each proxy should correctly call CloseStream() if OpenStream()
670 CloseAndWaitForCloseTimer(proxy2, &stream2);
673 CloseAndWaitForCloseTimer(proxy1, &stream1);
675 EXPECT_TRUE(stream1.stop_called());
676 EXPECT_TRUE(stream1.start_called());
677 EXPECT_TRUE(stream2.stop_called());
678 EXPECT_TRUE(stream2.start_called());
681 // Ensures the methods used to fix audio output wedges are working correctly.
682 TEST_F(AudioOutputResamplerTest, WedgeFix) {
683 MockAudioOutputStream stream1(&manager_, params_);
684 MockAudioOutputStream stream2(&manager_, params_);
685 MockAudioOutputStream stream3(&manager_, params_);
687 // Setup the mock such that all three streams are successfully created.
688 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
689 .WillOnce(Return(&stream1))
690 .WillOnce(Return(&stream2))
691 .WillOnce(Return(&stream3));
693 // Stream1 should be able to successfully open and start.
694 EXPECT_CALL(stream1, Open())
695 .WillOnce(Return(true));
696 EXPECT_CALL(stream1, SetVolume(_));
697 EXPECT_CALL(stream2, Open())
698 .WillOnce(Return(true));
699 EXPECT_CALL(stream2, SetVolume(_));
701 // Open and start the first proxy and stream.
702 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_.get());
703 EXPECT_TRUE(proxy1->Open());
704 proxy1->Start(&callback_);
707 // Open, but do not start the second proxy.
708 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get());
709 EXPECT_TRUE(proxy2->Open());
711 // Open, start and then stop the third proxy.
712 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get());
713 EXPECT_TRUE(proxy3->Open());
714 proxy3->Start(&callback_);
718 // Wait for stream to timeout and shutdown.
719 WaitForCloseTimer(&stream2);
721 EXPECT_CALL(stream1, Close());
722 resampler_->CloseStreamsForWedgeFix();
724 // Don't pump the MessageLoop between CloseStreamsForWedgeFix() and
725 // RestartStreamsForWedgeFix() to simulate intended usage. The OnStart() call
726 // will take care of necessary work.
728 // Stream3 should take Stream1's place after RestartStreamsForWedgeFix(). No
729 // additional streams should be opened for proxy2 and proxy3.
730 EXPECT_CALL(stream3, Open())
731 .WillOnce(Return(true));
732 EXPECT_CALL(stream3, SetVolume(_));
734 resampler_->RestartStreamsForWedgeFix();
737 // Perform the required Stop()/Close() shutdown dance for each proxy.
741 CloseAndWaitForCloseTimer(proxy1, &stream3);
743 // Wait for all of the messages to fly and then verify stream behavior.
744 EXPECT_TRUE(stream1.stop_called());
745 EXPECT_TRUE(stream1.start_called());
746 EXPECT_TRUE(stream2.stop_called());
747 EXPECT_TRUE(stream2.start_called());
748 EXPECT_TRUE(stream3.stop_called());
749 EXPECT_TRUE(stream3.start_called());