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