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.
5 #include "base/basictypes.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"
21 using ::testing::AtLeast;
22 using ::testing::DoAll;
23 using ::testing::Invoke;
24 using ::testing::NotNull;
25 using ::testing::Return;
29 static const int kSampleRate = AudioParameters::kAudioCDSampleRate;
30 static const int kBitsPerSample = 16;
31 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
32 static const int kSamplesPerPacket = kSampleRate / 100;
33 static const double kTestVolume = 0.25;
35 class MockAudioOutputControllerEventHandler
36 : public AudioOutputController::EventHandler {
38 MockAudioOutputControllerEventHandler() {}
40 MOCK_METHOD0(OnCreated, void());
41 MOCK_METHOD0(OnPlaying, void());
42 MOCK_METHOD2(OnPowerMeasured, void(float power_dbfs, bool clipped));
43 MOCK_METHOD0(OnPaused, void());
44 MOCK_METHOD0(OnError, void());
45 MOCK_METHOD2(OnDeviceChange, void(int new_buffer_size, int new_sample_rate));
48 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler);
51 class MockAudioOutputControllerSyncReader
52 : public AudioOutputController::SyncReader {
54 MockAudioOutputControllerSyncReader() {}
56 MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes));
57 MOCK_METHOD2(Read, void(const AudioBus* source, AudioBus* dest));
58 MOCK_METHOD0(Close, void());
61 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
64 class MockAudioOutputStream : public AudioOutputStream {
66 MOCK_METHOD0(Open, bool());
67 MOCK_METHOD1(Start, void(AudioSourceCallback* callback));
68 MOCK_METHOD0(Stop, void());
69 MOCK_METHOD1(SetVolume, void(double volume));
70 MOCK_METHOD1(GetVolume, void(double* volume));
71 MOCK_METHOD0(Close, void());
73 // Set/get the callback passed to Start().
74 AudioSourceCallback* callback() const { return callback_; }
75 void SetCallback(AudioSourceCallback* asc) { callback_ = asc; }
78 AudioSourceCallback* callback_;
81 ACTION_P(SignalEvent, event) {
85 static const float kBufferNonZeroData = 1.0f;
86 ACTION(PopulateBuffer) {
88 // Note: To confirm the buffer will be populated in these tests, it's
89 // sufficient that only the first float in channel 0 is set to the value.
90 arg1->channel(0)[0] = kBufferNonZeroData;
93 class AudioOutputControllerTest : public testing::Test {
95 AudioOutputControllerTest()
96 : audio_manager_(AudioManager::Create()),
97 create_event_(false, false),
98 play_event_(false, false),
99 read_event_(false, false),
100 pause_event_(false, false) {
103 virtual ~AudioOutputControllerTest() {
107 void Create(int samples_per_packet) {
108 EXPECT_FALSE(create_event_.IsSignaled());
109 EXPECT_FALSE(play_event_.IsSignaled());
110 EXPECT_FALSE(read_event_.IsSignaled());
111 EXPECT_FALSE(pause_event_.IsSignaled());
113 params_ = AudioParameters(
114 AudioParameters::AUDIO_FAKE, kChannelLayout,
115 kSampleRate, kBitsPerSample, samples_per_packet);
117 if (params_.IsValid()) {
118 EXPECT_CALL(mock_event_handler_, OnCreated())
119 .WillOnce(SignalEvent(&create_event_));
122 controller_ = AudioOutputController::Create(
123 audio_manager_.get(), &mock_event_handler_, params_, std::string(),
124 std::string(), &mock_sync_reader_);
125 if (controller_.get())
126 controller_->SetVolume(kTestVolume);
128 EXPECT_EQ(params_.IsValid(), controller_.get() != NULL);
132 // Expect the event handler to receive one OnPlaying() call and one or more
133 // OnPowerMeasured() calls.
134 EXPECT_CALL(mock_event_handler_, OnPlaying())
135 .WillOnce(SignalEvent(&play_event_));
136 #if defined(AUDIO_POWER_MONITORING)
137 EXPECT_CALL(mock_event_handler_, OnPowerMeasured(_, false))
141 // During playback, the mock pretends to provide audio data rendered and
142 // sent from the render process.
143 EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_))
145 EXPECT_CALL(mock_sync_reader_, Read(_, _))
146 .WillRepeatedly(DoAll(PopulateBuffer(),
147 SignalEvent(&read_event_)));
152 // Expect the event handler to receive one OnPaused() call.
153 EXPECT_CALL(mock_event_handler_, OnPaused())
154 .WillOnce(SignalEvent(&pause_event_));
156 controller_->Pause();
159 void ChangeDevice() {
160 // Expect the event handler to receive one OnPaying() call and no OnPaused()
162 EXPECT_CALL(mock_event_handler_, OnPlaying())
163 .WillOnce(SignalEvent(&play_event_));
164 EXPECT_CALL(mock_event_handler_, OnPaused())
167 // Simulate a device change event to AudioOutputController from the
169 audio_manager_->GetMessageLoop()->PostTask(
171 base::Bind(&AudioOutputController::OnDeviceChange, controller_));
174 void Divert(bool was_playing, int num_times_to_be_started) {
176 // Expect the handler to receive one OnPlaying() call as a result of the
178 EXPECT_CALL(mock_event_handler_, OnPlaying())
179 .WillOnce(SignalEvent(&play_event_));
182 EXPECT_CALL(mock_stream_, Open())
183 .WillOnce(Return(true));
184 EXPECT_CALL(mock_stream_, SetVolume(kTestVolume));
185 if (num_times_to_be_started > 0) {
186 EXPECT_CALL(mock_stream_, Start(NotNull()))
187 .Times(num_times_to_be_started)
189 Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback));
190 EXPECT_CALL(mock_stream_, Stop())
191 .Times(num_times_to_be_started);
194 controller_->StartDiverting(&mock_stream_);
197 void ReadDivertedAudioData() {
198 scoped_ptr<AudioBus> dest = AudioBus::Create(params_);
199 ASSERT_TRUE(!!mock_stream_.callback());
200 const int frames_read =
201 mock_stream_.callback()->OnMoreData(dest.get(), AudioBuffersState());
202 EXPECT_LT(0, frames_read);
203 EXPECT_EQ(kBufferNonZeroData, dest->channel(0)[0]);
206 void Revert(bool was_playing) {
208 // Expect the handler to receive one OnPlaying() call as a result of the
209 // stream switching back.
210 EXPECT_CALL(mock_event_handler_, OnPlaying())
211 .WillOnce(SignalEvent(&play_event_));
214 EXPECT_CALL(mock_stream_, Close());
216 controller_->StopDiverting();
219 void SwitchDevice(bool diverting) {
221 // Expect the current stream to close and a new stream to start
222 // playing if not diverting. When diverting, nothing happens
223 // until diverting is stopped.
224 EXPECT_CALL(mock_event_handler_, OnPlaying())
225 .WillOnce(SignalEvent(&play_event_));
228 controller_->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName,
229 base::Bind(&base::DoNothing));
233 EXPECT_CALL(mock_sync_reader_, Close());
235 controller_->Close(base::MessageLoop::QuitClosure());
236 base::MessageLoop::current()->Run();
239 // These help make test sequences more readable.
240 void DivertNeverPlaying() { Divert(false, 0); }
241 void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); }
242 void DivertWhilePlaying() { Divert(true, 1); }
243 void RevertWasNotPlaying() { Revert(false); }
244 void RevertWhilePlaying() { Revert(true); }
246 // These synchronize the main thread with key events taking place on other
248 void WaitForCreate() { create_event_.Wait(); }
249 void WaitForPlay() { play_event_.Wait(); }
250 void WaitForReads() {
251 // Note: Arbitrarily chosen, but more iterations causes tests to take
252 // significantly more time.
253 static const int kNumIterations = 3;
254 for (int i = 0; i < kNumIterations; ++i) {
258 void WaitForPause() { pause_event_.Wait(); }
261 base::MessageLoopForIO message_loop_;
262 scoped_ptr<AudioManager> audio_manager_;
263 MockAudioOutputControllerEventHandler mock_event_handler_;
264 MockAudioOutputControllerSyncReader mock_sync_reader_;
265 MockAudioOutputStream mock_stream_;
266 base::WaitableEvent create_event_;
267 base::WaitableEvent play_event_;
268 base::WaitableEvent read_event_;
269 base::WaitableEvent pause_event_;
270 AudioParameters params_;
271 scoped_refptr<AudioOutputController> controller_;
273 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest);
276 TEST_F(AudioOutputControllerTest, CreateAndClose) {
277 Create(kSamplesPerPacket);
281 TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
282 Create(kSamplesPerPacket * 1000);
285 TEST_F(AudioOutputControllerTest, PlayAndClose) {
286 Create(kSamplesPerPacket);
294 TEST_F(AudioOutputControllerTest, PlayPauseClose) {
295 Create(kSamplesPerPacket);
305 TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
306 Create(kSamplesPerPacket);
318 TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
319 Create(kSamplesPerPacket);
330 TEST_F(AudioOutputControllerTest, PlaySwitchDeviceClose) {
331 Create(kSamplesPerPacket);
342 TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
343 Create(kSamplesPerPacket);
348 DivertWhilePlaying();
350 ReadDivertedAudioData();
351 RevertWhilePlaying();
357 TEST_F(AudioOutputControllerTest, PlayDivertSwitchDeviceRevertClose) {
358 Create(kSamplesPerPacket);
363 DivertWhilePlaying();
366 ReadDivertedAudioData();
367 RevertWhilePlaying();
373 TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) {
374 Create(kSamplesPerPacket);
379 DivertWhilePlaying();
381 ReadDivertedAudioData();
382 RevertWhilePlaying();
385 DivertWhilePlaying();
387 ReadDivertedAudioData();
388 RevertWhilePlaying();
394 TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) {
395 Create(kSamplesPerPacket);
397 DivertWillEventuallyBeTwicePlayed();
400 ReadDivertedAudioData();
405 ReadDivertedAudioData();
406 RevertWhilePlaying();
412 TEST_F(AudioOutputControllerTest, DivertRevertClose) {
413 Create(kSamplesPerPacket);
415 DivertNeverPlaying();
416 RevertWasNotPlaying();