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_output_controller.h"
14 #include "media/audio/audio_parameters.h"
15 #include "media/base/audio_bus.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
20 using ::testing::AtLeast
;
21 using ::testing::DoAll
;
22 using ::testing::Invoke
;
23 using ::testing::NotNull
;
24 using ::testing::Return
;
28 static const int kSampleRate
= AudioParameters::kAudioCDSampleRate
;
29 static const int kBitsPerSample
= 16;
30 static const ChannelLayout kChannelLayout
= CHANNEL_LAYOUT_STEREO
;
31 static const int kSamplesPerPacket
= kSampleRate
/ 100;
32 static const int kHardwareBufferSize
= kSamplesPerPacket
*
33 ChannelLayoutToChannelCount(kChannelLayout
) * kBitsPerSample
/ 8;
34 static const double kTestVolume
= 0.25;
36 class MockAudioOutputControllerEventHandler
37 : public AudioOutputController::EventHandler
{
39 MockAudioOutputControllerEventHandler() {}
41 MOCK_METHOD0(OnCreated
, void());
42 MOCK_METHOD0(OnPlaying
, void());
43 MOCK_METHOD2(OnPowerMeasured
, void(float power_dbfs
, bool clipped
));
44 MOCK_METHOD0(OnPaused
, void());
45 MOCK_METHOD0(OnError
, void());
46 MOCK_METHOD2(OnDeviceChange
, void(int new_buffer_size
, int new_sample_rate
));
49 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler
);
52 class MockAudioOutputControllerSyncReader
53 : public AudioOutputController::SyncReader
{
55 MockAudioOutputControllerSyncReader() {}
57 MOCK_METHOD1(UpdatePendingBytes
, void(uint32 bytes
));
58 MOCK_METHOD3(Read
, int(bool block
, const AudioBus
* source
, AudioBus
* dest
));
59 MOCK_METHOD0(Close
, void());
62 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader
);
65 class MockAudioOutputStream
: public AudioOutputStream
{
67 MOCK_METHOD0(Open
, bool());
68 MOCK_METHOD1(Start
, void(AudioSourceCallback
* callback
));
69 MOCK_METHOD0(Stop
, void());
70 MOCK_METHOD1(SetVolume
, void(double volume
));
71 MOCK_METHOD1(GetVolume
, void(double* volume
));
72 MOCK_METHOD0(Close
, void());
74 // Set/get the callback passed to Start().
75 AudioSourceCallback
* callback() const { return callback_
; }
76 void SetCallback(AudioSourceCallback
* asc
) { callback_
= asc
; }
79 AudioSourceCallback
* callback_
;
82 ACTION_P(SignalEvent
, event
) {
86 static const float kBufferNonZeroData
= 1.0f
;
87 ACTION(PopulateBuffer
) {
89 // Note: To confirm the buffer will be populated in these tests, it's
90 // sufficient that only the first float in channel 0 is set to the value.
91 arg2
->channel(0)[0] = kBufferNonZeroData
;
94 class AudioOutputControllerTest
: public testing::Test
{
96 AudioOutputControllerTest()
97 : audio_manager_(AudioManager::Create()),
98 create_event_(false, false),
99 play_event_(false, false),
100 read_event_(false, false),
101 pause_event_(false, false) {
104 virtual ~AudioOutputControllerTest() {
108 void Create(int samples_per_packet
) {
109 EXPECT_FALSE(create_event_
.IsSignaled());
110 EXPECT_FALSE(play_event_
.IsSignaled());
111 EXPECT_FALSE(read_event_
.IsSignaled());
112 EXPECT_FALSE(pause_event_
.IsSignaled());
114 params_
= AudioParameters(
115 AudioParameters::AUDIO_FAKE
, kChannelLayout
,
116 kSampleRate
, kBitsPerSample
, samples_per_packet
);
118 if (params_
.IsValid()) {
119 EXPECT_CALL(mock_event_handler_
, OnCreated())
120 .WillOnce(SignalEvent(&create_event_
));
123 controller_
= AudioOutputController::Create(
124 audio_manager_
.get(), &mock_event_handler_
, params_
, std::string(),
126 if (controller_
.get())
127 controller_
->SetVolume(kTestVolume
);
129 EXPECT_EQ(params_
.IsValid(), controller_
.get() != NULL
);
133 // Expect the event handler to receive one OnPlaying() call and one or more
134 // OnPowerMeasured() calls.
135 EXPECT_CALL(mock_event_handler_
, OnPlaying())
136 .WillOnce(SignalEvent(&play_event_
));
137 EXPECT_CALL(mock_event_handler_
, OnPowerMeasured(_
, false))
140 // During playback, the mock pretends to provide audio data rendered and
141 // sent from the render process.
142 EXPECT_CALL(mock_sync_reader_
, UpdatePendingBytes(_
))
144 EXPECT_CALL(mock_sync_reader_
, Read(_
, _
, _
))
145 .WillRepeatedly(DoAll(PopulateBuffer(),
146 SignalEvent(&read_event_
),
147 Return(params_
.frames_per_buffer())));
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();
220 EXPECT_CALL(mock_sync_reader_
, Close());
222 controller_
->Close(base::MessageLoop::QuitClosure());
223 base::MessageLoop::current()->Run();
226 // These help make test sequences more readable.
227 void DivertNeverPlaying() { Divert(false, 0); }
228 void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); }
229 void DivertWhilePlaying() { Divert(true, 1); }
230 void RevertWasNotPlaying() { Revert(false); }
231 void RevertWhilePlaying() { Revert(true); }
233 // These synchronize the main thread with key events taking place on other
235 void WaitForCreate() { create_event_
.Wait(); }
236 void WaitForPlay() { play_event_
.Wait(); }
237 void WaitForReads() {
238 // Note: Arbitrarily chosen, but more iterations causes tests to take
239 // significantly more time.
240 static const int kNumIterations
= 3;
241 for (int i
= 0; i
< kNumIterations
; ++i
) {
245 void WaitForPause() { pause_event_
.Wait(); }
248 base::MessageLoopForIO message_loop_
;
249 scoped_ptr
<AudioManager
> audio_manager_
;
250 MockAudioOutputControllerEventHandler mock_event_handler_
;
251 MockAudioOutputControllerSyncReader mock_sync_reader_
;
252 MockAudioOutputStream mock_stream_
;
253 base::WaitableEvent create_event_
;
254 base::WaitableEvent play_event_
;
255 base::WaitableEvent read_event_
;
256 base::WaitableEvent pause_event_
;
257 AudioParameters params_
;
258 scoped_refptr
<AudioOutputController
> controller_
;
260 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest
);
263 TEST_F(AudioOutputControllerTest
, CreateAndClose
) {
264 Create(kSamplesPerPacket
);
268 TEST_F(AudioOutputControllerTest
, HardwareBufferTooLarge
) {
269 Create(kSamplesPerPacket
* 1000);
272 TEST_F(AudioOutputControllerTest
, PlayAndClose
) {
273 Create(kSamplesPerPacket
);
281 TEST_F(AudioOutputControllerTest
, PlayPauseClose
) {
282 Create(kSamplesPerPacket
);
292 TEST_F(AudioOutputControllerTest
, PlayPausePlayClose
) {
293 Create(kSamplesPerPacket
);
305 TEST_F(AudioOutputControllerTest
, PlayDeviceChangeClose
) {
306 Create(kSamplesPerPacket
);
317 TEST_F(AudioOutputControllerTest
, PlayDivertRevertClose
) {
318 Create(kSamplesPerPacket
);
323 DivertWhilePlaying();
325 ReadDivertedAudioData();
326 RevertWhilePlaying();
332 TEST_F(AudioOutputControllerTest
, PlayDivertRevertDivertRevertClose
) {
333 Create(kSamplesPerPacket
);
338 DivertWhilePlaying();
340 ReadDivertedAudioData();
341 RevertWhilePlaying();
344 DivertWhilePlaying();
346 ReadDivertedAudioData();
347 RevertWhilePlaying();
353 TEST_F(AudioOutputControllerTest
, DivertPlayPausePlayRevertClose
) {
354 Create(kSamplesPerPacket
);
356 DivertWillEventuallyBeTwicePlayed();
359 ReadDivertedAudioData();
364 ReadDivertedAudioData();
365 RevertWhilePlaying();
371 TEST_F(AudioOutputControllerTest
, DivertRevertClose
) {
372 Create(kSamplesPerPacket
);
374 DivertNeverPlaying();
375 RevertWasNotPlaying();