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