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