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
19using ::testing::_;
20using ::testing::AllOf;
21using ::testing::DoAll;
22using ::testing::Field;
23using ::testing::Mock;
24using ::testing::NotNull;
25using ::testing::Return;
26using ::testing::SetArrayArgument;
27using media::AudioBus;
28using media::AudioBuffersState;
29using media::AudioInputStream;
30using media::AudioManager;
31using media::AudioManagerBase;
32using media::AudioOutputDispatcher;
33using media::AudioOutputProxy;
34using media::AudioOutputStream;
35using media::AudioParameters;
36using media::FakeAudioOutputStream;
37
38namespace {
39
40static const int kTestCloseDelayMs = 10;
41
42// Delay between callbacks to AudioSourceCallback::OnMoreData.
43static const int kOnMoreDataCallbackDelayMs = 10;
44
45// Let start run long enough for many OnMoreData callbacks to occur.
46static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10;
47
48class 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
86class 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
126class 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
137namespace media {
138
139class 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
415class 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
447TEST_F(AudioOutputProxyTest, CreateAndClose) {
448  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_.get());
449  proxy->Close();
450}
451
452TEST_F(AudioOutputResamplerTest, CreateAndClose) {
453  AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get());
454  proxy->Close();
455}
456
457TEST_F(AudioOutputProxyTest, OpenAndClose) {
458  OpenAndClose(dispatcher_impl_.get());
459}
460
461TEST_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.
467TEST_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.
473TEST_F(AudioOutputResamplerTest, CreateAndWait) {
474  CreateAndWait(resampler_.get());
475}
476
477TEST_F(AudioOutputProxyTest, StartAndStop) {
478  StartAndStop(dispatcher_impl_.get());
479}
480
481TEST_F(AudioOutputResamplerTest, StartAndStop) {
482  StartAndStop(resampler_.get());
483}
484
485TEST_F(AudioOutputProxyTest, CloseAfterStop) {
486  CloseAfterStop(dispatcher_impl_.get());
487}
488
489TEST_F(AudioOutputResamplerTest, CloseAfterStop) {
490  CloseAfterStop(resampler_.get());
491}
492
493TEST_F(AudioOutputProxyTest, TwoStreams) {
494  TwoStreams(dispatcher_impl_.get());
495}
496
497TEST_F(AudioOutputResamplerTest, TwoStreams) {
498  TwoStreams(resampler_.get());
499}
500
501// Two streams: verify that second stream is allocated when the first
502// starts playing.
503TEST_F(AudioOutputProxyTest, OneStream_TwoPlays) {
504  OneStream_TwoPlays(dispatcher_impl_.get());
505}
506
507TEST_F(AudioOutputResamplerTest, OneStream_TwoPlays) {
508  OneStream_TwoPlays(resampler_.get());
509}
510
511// Two streams, both are playing. Dispatcher should not open a third stream.
512TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
513  TwoStreams_BothPlaying(dispatcher_impl_.get());
514}
515
516TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) {
517  TwoStreams_BothPlaying(resampler_.get());
518}
519
520TEST_F(AudioOutputProxyTest, OpenFailed) {
521  OpenFailed(dispatcher_impl_.get());
522}
523
524// Start() method failed.
525TEST_F(AudioOutputProxyTest, StartFailed) {
526  StartFailed(dispatcher_impl_.get());
527}
528
529TEST_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.
535TEST_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.
551TEST_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.
572TEST_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.
607TEST_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
626TEST_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
681