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::CreateForTesting()),
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_
->GetTaskRunner()->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();