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 "base/basictypes.h"
6#include "base/bind.h"
7#include "base/environment.h"
8#include "base/logging.h"
9#include "base/memory/ref_counted.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/message_loop/message_loop.h"
12#include "base/synchronization/waitable_event.h"
13#include "media/audio/audio_manager_base.h"
14#include "media/audio/audio_output_controller.h"
15#include "media/audio/audio_parameters.h"
16#include "media/base/audio_bus.h"
17#include "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using ::testing::_;
21using ::testing::AtLeast;
22using ::testing::DoAll;
23using ::testing::Invoke;
24using ::testing::NotNull;
25using ::testing::Return;
26
27namespace media {
28
29static const int kSampleRate = AudioParameters::kAudioCDSampleRate;
30static const int kBitsPerSample = 16;
31static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
32static const int kSamplesPerPacket = kSampleRate / 100;
33static const double kTestVolume = 0.25;
34
35class MockAudioOutputControllerEventHandler
36    : public AudioOutputController::EventHandler {
37 public:
38  MockAudioOutputControllerEventHandler() {}
39
40  MOCK_METHOD0(OnCreated, void());
41  MOCK_METHOD0(OnPlaying, void());
42  MOCK_METHOD0(OnPaused, void());
43  MOCK_METHOD0(OnError, void());
44  MOCK_METHOD2(OnDeviceChange, void(int new_buffer_size, int new_sample_rate));
45
46 private:
47  DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler);
48};
49
50class MockAudioOutputControllerSyncReader
51    : public AudioOutputController::SyncReader {
52 public:
53  MockAudioOutputControllerSyncReader() {}
54
55  MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes));
56  MOCK_METHOD1(Read, void(AudioBus* dest));
57  MOCK_METHOD0(Close, void());
58
59 private:
60  DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
61};
62
63class MockAudioOutputStream : public AudioOutputStream {
64 public:
65  MOCK_METHOD0(Open, bool());
66  MOCK_METHOD1(Start, void(AudioSourceCallback* callback));
67  MOCK_METHOD0(Stop, void());
68  MOCK_METHOD1(SetVolume, void(double volume));
69  MOCK_METHOD1(GetVolume, void(double* volume));
70  MOCK_METHOD0(Close, void());
71
72  // Set/get the callback passed to Start().
73  AudioSourceCallback* callback() const { return callback_; }
74  void SetCallback(AudioSourceCallback* asc) { callback_ = asc; }
75
76 private:
77  AudioSourceCallback* callback_;
78};
79
80ACTION_P(SignalEvent, event) {
81  event->Signal();
82}
83
84static const float kBufferNonZeroData = 1.0f;
85ACTION(PopulateBuffer) {
86  arg0->Zero();
87  // Note: To confirm the buffer will be populated in these tests, it's
88  // sufficient that only the first float in channel 0 is set to the value.
89  arg0->channel(0)[0] = kBufferNonZeroData;
90}
91
92class AudioOutputControllerTest : public testing::Test {
93 public:
94  AudioOutputControllerTest()
95      : audio_manager_(AudioManager::CreateForTesting()),
96        create_event_(false, false),
97        play_event_(false, false),
98        read_event_(false, false),
99        pause_event_(false, false) {
100  }
101
102  virtual ~AudioOutputControllerTest() {
103  }
104
105 protected:
106  void Create(int samples_per_packet) {
107    EXPECT_FALSE(create_event_.IsSignaled());
108    EXPECT_FALSE(play_event_.IsSignaled());
109    EXPECT_FALSE(read_event_.IsSignaled());
110    EXPECT_FALSE(pause_event_.IsSignaled());
111
112    params_ = AudioParameters(
113        AudioParameters::AUDIO_FAKE, kChannelLayout,
114        kSampleRate, kBitsPerSample, samples_per_packet);
115
116    if (params_.IsValid()) {
117      EXPECT_CALL(mock_event_handler_, OnCreated())
118          .WillOnce(SignalEvent(&create_event_));
119    }
120
121    controller_ = AudioOutputController::Create(
122        audio_manager_.get(), &mock_event_handler_, params_, std::string(),
123        &mock_sync_reader_);
124    if (controller_.get())
125      controller_->SetVolume(kTestVolume);
126
127    EXPECT_EQ(params_.IsValid(), controller_.get() != NULL);
128  }
129
130  void Play() {
131    // Expect the event handler to receive one OnPlaying() call.
132    EXPECT_CALL(mock_event_handler_, OnPlaying())
133        .WillOnce(SignalEvent(&play_event_));
134
135    // During playback, the mock pretends to provide audio data rendered and
136    // sent from the render process.
137    EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_))
138        .Times(AtLeast(1));
139    EXPECT_CALL(mock_sync_reader_, Read(_))
140        .WillRepeatedly(DoAll(PopulateBuffer(),
141                              SignalEvent(&read_event_)));
142    controller_->Play();
143  }
144
145  void Pause() {
146    // Expect the event handler to receive one OnPaused() call.
147    EXPECT_CALL(mock_event_handler_, OnPaused())
148        .WillOnce(SignalEvent(&pause_event_));
149
150    controller_->Pause();
151  }
152
153  void ChangeDevice() {
154    // Expect the event handler to receive one OnPaying() call and no OnPaused()
155    // call.
156    EXPECT_CALL(mock_event_handler_, OnPlaying())
157        .WillOnce(SignalEvent(&play_event_));
158    EXPECT_CALL(mock_event_handler_, OnPaused())
159        .Times(0);
160
161    // Simulate a device change event to AudioOutputController from the
162    // AudioManager.
163    audio_manager_->GetTaskRunner()->PostTask(
164        FROM_HERE,
165        base::Bind(&AudioOutputController::OnDeviceChange, controller_));
166  }
167
168  void Divert(bool was_playing, int num_times_to_be_started) {
169    if (was_playing) {
170      // Expect the handler to receive one OnPlaying() call as a result of the
171      // stream switching.
172      EXPECT_CALL(mock_event_handler_, OnPlaying())
173          .WillOnce(SignalEvent(&play_event_));
174    }
175
176    EXPECT_CALL(mock_stream_, Open())
177        .WillOnce(Return(true));
178    EXPECT_CALL(mock_stream_, SetVolume(kTestVolume));
179    if (num_times_to_be_started > 0) {
180      EXPECT_CALL(mock_stream_, Start(NotNull()))
181          .Times(num_times_to_be_started)
182          .WillRepeatedly(
183              Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback));
184      EXPECT_CALL(mock_stream_, Stop())
185          .Times(num_times_to_be_started);
186    }
187
188    controller_->StartDiverting(&mock_stream_);
189  }
190
191  void ReadDivertedAudioData() {
192    scoped_ptr<AudioBus> dest = AudioBus::Create(params_);
193    ASSERT_TRUE(!!mock_stream_.callback());
194    const int frames_read =
195        mock_stream_.callback()->OnMoreData(dest.get(), AudioBuffersState());
196    EXPECT_LT(0, frames_read);
197    EXPECT_EQ(kBufferNonZeroData, dest->channel(0)[0]);
198  }
199
200  void Revert(bool was_playing) {
201    if (was_playing) {
202      // Expect the handler to receive one OnPlaying() call as a result of the
203      // stream switching back.
204      EXPECT_CALL(mock_event_handler_, OnPlaying())
205          .WillOnce(SignalEvent(&play_event_));
206    }
207
208    EXPECT_CALL(mock_stream_, Close());
209
210    controller_->StopDiverting();
211  }
212
213  void SwitchDevice(bool diverting) {
214    if (!diverting) {
215      // Expect the current stream to close and a new stream to start
216      // playing if not diverting. When diverting, nothing happens
217      // until diverting is stopped.
218      EXPECT_CALL(mock_event_handler_, OnPlaying())
219          .WillOnce(SignalEvent(&play_event_));
220    }
221
222    controller_->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName,
223                                    base::Bind(&base::DoNothing));
224  }
225
226  void Close() {
227    EXPECT_CALL(mock_sync_reader_, Close());
228
229    controller_->Close(base::MessageLoop::QuitClosure());
230    base::MessageLoop::current()->Run();
231  }
232
233  // These help make test sequences more readable.
234  void DivertNeverPlaying() { Divert(false, 0); }
235  void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); }
236  void DivertWhilePlaying() { Divert(true, 1); }
237  void RevertWasNotPlaying() { Revert(false); }
238  void RevertWhilePlaying() { Revert(true); }
239
240  // These synchronize the main thread with key events taking place on other
241  // threads.
242  void WaitForCreate() { create_event_.Wait(); }
243  void WaitForPlay() { play_event_.Wait(); }
244  void WaitForReads() {
245    // Note: Arbitrarily chosen, but more iterations causes tests to take
246    // significantly more time.
247    static const int kNumIterations = 3;
248    for (int i = 0; i < kNumIterations; ++i) {
249      read_event_.Wait();
250    }
251  }
252  void WaitForPause() { pause_event_.Wait(); }
253
254 private:
255  base::MessageLoopForIO message_loop_;
256  scoped_ptr<AudioManager> audio_manager_;
257  MockAudioOutputControllerEventHandler mock_event_handler_;
258  MockAudioOutputControllerSyncReader mock_sync_reader_;
259  MockAudioOutputStream mock_stream_;
260  base::WaitableEvent create_event_;
261  base::WaitableEvent play_event_;
262  base::WaitableEvent read_event_;
263  base::WaitableEvent pause_event_;
264  AudioParameters params_;
265  scoped_refptr<AudioOutputController> controller_;
266
267  DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest);
268};
269
270TEST_F(AudioOutputControllerTest, CreateAndClose) {
271  Create(kSamplesPerPacket);
272  Close();
273}
274
275TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
276  Create(kSamplesPerPacket * 1000);
277}
278
279TEST_F(AudioOutputControllerTest, PlayAndClose) {
280  Create(kSamplesPerPacket);
281  WaitForCreate();
282  Play();
283  WaitForPlay();
284  WaitForReads();
285  Close();
286}
287
288TEST_F(AudioOutputControllerTest, PlayPauseClose) {
289  Create(kSamplesPerPacket);
290  WaitForCreate();
291  Play();
292  WaitForPlay();
293  WaitForReads();
294  Pause();
295  WaitForPause();
296  Close();
297}
298
299TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
300  Create(kSamplesPerPacket);
301  WaitForCreate();
302  Play();
303  WaitForPlay();
304  WaitForReads();
305  Pause();
306  WaitForPause();
307  Play();
308  WaitForPlay();
309  Close();
310}
311
312TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
313  Create(kSamplesPerPacket);
314  WaitForCreate();
315  Play();
316  WaitForPlay();
317  WaitForReads();
318  ChangeDevice();
319  WaitForPlay();
320  WaitForReads();
321  Close();
322}
323
324TEST_F(AudioOutputControllerTest, PlaySwitchDeviceClose) {
325  Create(kSamplesPerPacket);
326  WaitForCreate();
327  Play();
328  WaitForPlay();
329  WaitForReads();
330  SwitchDevice(false);
331  WaitForPlay();
332  WaitForReads();
333  Close();
334}
335
336TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
337  Create(kSamplesPerPacket);
338  WaitForCreate();
339  Play();
340  WaitForPlay();
341  WaitForReads();
342  DivertWhilePlaying();
343  WaitForPlay();
344  ReadDivertedAudioData();
345  RevertWhilePlaying();
346  WaitForPlay();
347  WaitForReads();
348  Close();
349}
350
351TEST_F(AudioOutputControllerTest, PlayDivertSwitchDeviceRevertClose) {
352  Create(kSamplesPerPacket);
353  WaitForCreate();
354  Play();
355  WaitForPlay();
356  WaitForReads();
357  DivertWhilePlaying();
358  WaitForPlay();
359  SwitchDevice(true);
360  ReadDivertedAudioData();
361  RevertWhilePlaying();
362  WaitForPlay();
363  WaitForReads();
364  Close();
365}
366
367TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) {
368  Create(kSamplesPerPacket);
369  WaitForCreate();
370  Play();
371  WaitForPlay();
372  WaitForReads();
373  DivertWhilePlaying();
374  WaitForPlay();
375  ReadDivertedAudioData();
376  RevertWhilePlaying();
377  WaitForPlay();
378  WaitForReads();
379  DivertWhilePlaying();
380  WaitForPlay();
381  ReadDivertedAudioData();
382  RevertWhilePlaying();
383  WaitForPlay();
384  WaitForReads();
385  Close();
386}
387
388TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) {
389  Create(kSamplesPerPacket);
390  WaitForCreate();
391  DivertWillEventuallyBeTwicePlayed();
392  Play();
393  WaitForPlay();
394  ReadDivertedAudioData();
395  Pause();
396  WaitForPause();
397  Play();
398  WaitForPlay();
399  ReadDivertedAudioData();
400  RevertWhilePlaying();
401  WaitForPlay();
402  WaitForReads();
403  Close();
404}
405
406TEST_F(AudioOutputControllerTest, DivertRevertClose) {
407  Create(kSamplesPerPacket);
408  WaitForCreate();
409  DivertNeverPlaying();
410  RevertWasNotPlaying();
411  Close();
412}
413
414}  // namespace media
415