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_METHOD0(OnPaused
, void());
43 MOCK_METHOD0(OnError
, void());
46 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler
);
49 class MockAudioOutputControllerSyncReader
50 : public AudioOutputController::SyncReader
{
52 MockAudioOutputControllerSyncReader() {}
54 MOCK_METHOD1(UpdatePendingBytes
, void(uint32 bytes
));
55 MOCK_METHOD1(Read
, void(AudioBus
* dest
));
56 MOCK_METHOD0(Close
, void());
59 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader
);
62 class MockAudioOutputStream
: public AudioOutputStream
{
64 MOCK_METHOD0(Open
, bool());
65 MOCK_METHOD1(Start
, void(AudioSourceCallback
* callback
));
66 MOCK_METHOD0(Stop
, void());
67 MOCK_METHOD1(SetVolume
, void(double volume
));
68 MOCK_METHOD1(GetVolume
, void(double* volume
));
69 MOCK_METHOD0(Close
, void());
71 // Set/get the callback passed to Start().
72 AudioSourceCallback
* callback() const { return callback_
; }
73 void SetCallback(AudioSourceCallback
* asc
) { callback_
= asc
; }
76 AudioSourceCallback
* callback_
;
79 ACTION_P(SignalEvent
, event
) {
83 static const float kBufferNonZeroData
= 1.0f
;
84 ACTION(PopulateBuffer
) {
86 // Note: To confirm the buffer will be populated in these tests, it's
87 // sufficient that only the first float in channel 0 is set to the value.
88 arg0
->channel(0)[0] = kBufferNonZeroData
;
91 class AudioOutputControllerTest
: public testing::Test
{
93 AudioOutputControllerTest()
94 : audio_manager_(AudioManager::CreateForTesting()),
95 create_event_(false, false),
96 play_event_(false, false),
97 read_event_(false, false),
98 pause_event_(false, false) {
101 ~AudioOutputControllerTest() override
{}
104 void Create(int samples_per_packet
) {
105 EXPECT_FALSE(create_event_
.IsSignaled());
106 EXPECT_FALSE(play_event_
.IsSignaled());
107 EXPECT_FALSE(read_event_
.IsSignaled());
108 EXPECT_FALSE(pause_event_
.IsSignaled());
110 params_
= AudioParameters(
111 AudioParameters::AUDIO_FAKE
, kChannelLayout
,
112 kSampleRate
, kBitsPerSample
, samples_per_packet
);
114 if (params_
.IsValid()) {
115 EXPECT_CALL(mock_event_handler_
, OnCreated())
116 .WillOnce(SignalEvent(&create_event_
));
119 controller_
= AudioOutputController::Create(
120 audio_manager_
.get(), &mock_event_handler_
, params_
, std::string(),
122 if (controller_
.get())
123 controller_
->SetVolume(kTestVolume
);
125 EXPECT_EQ(params_
.IsValid(), controller_
.get() != NULL
);
129 // Expect the event handler to receive one OnPlaying() call.
130 EXPECT_CALL(mock_event_handler_
, OnPlaying())
131 .WillOnce(SignalEvent(&play_event_
));
133 // During playback, the mock pretends to provide audio data rendered and
134 // sent from the render process.
135 EXPECT_CALL(mock_sync_reader_
, UpdatePendingBytes(_
))
137 EXPECT_CALL(mock_sync_reader_
, Read(_
))
138 .WillRepeatedly(DoAll(PopulateBuffer(),
139 SignalEvent(&read_event_
)));
144 // Expect the event handler to receive one OnPaused() call.
145 EXPECT_CALL(mock_event_handler_
, OnPaused())
146 .WillOnce(SignalEvent(&pause_event_
));
148 controller_
->Pause();
151 void ChangeDevice() {
152 // Expect the event handler to receive one OnPaying() call and no OnPaused()
154 EXPECT_CALL(mock_event_handler_
, OnPlaying())
155 .WillOnce(SignalEvent(&play_event_
));
156 EXPECT_CALL(mock_event_handler_
, OnPaused())
159 // Simulate a device change event to AudioOutputController from the
161 audio_manager_
->GetTaskRunner()->PostTask(
163 base::Bind(&AudioOutputController::OnDeviceChange
, controller_
));
166 void Divert(bool was_playing
, int num_times_to_be_started
) {
168 // Expect the handler to receive one OnPlaying() call as a result of the
170 EXPECT_CALL(mock_event_handler_
, OnPlaying())
171 .WillOnce(SignalEvent(&play_event_
));
174 EXPECT_CALL(mock_stream_
, Open())
175 .WillOnce(Return(true));
176 EXPECT_CALL(mock_stream_
, SetVolume(kTestVolume
));
177 if (num_times_to_be_started
> 0) {
178 EXPECT_CALL(mock_stream_
, Start(NotNull()))
179 .Times(num_times_to_be_started
)
181 Invoke(&mock_stream_
, &MockAudioOutputStream::SetCallback
));
182 EXPECT_CALL(mock_stream_
, Stop())
183 .Times(num_times_to_be_started
);
186 controller_
->StartDiverting(&mock_stream_
);
189 void ReadDivertedAudioData() {
190 scoped_ptr
<AudioBus
> dest
= AudioBus::Create(params_
);
191 ASSERT_TRUE(mock_stream_
.callback());
192 const int frames_read
=
193 mock_stream_
.callback()->OnMoreData(dest
.get(), 0);
194 EXPECT_LT(0, frames_read
);
195 EXPECT_EQ(kBufferNonZeroData
, dest
->channel(0)[0]);
198 void Revert(bool was_playing
) {
200 // Expect the handler to receive one OnPlaying() call as a result of the
201 // stream switching back.
202 EXPECT_CALL(mock_event_handler_
, OnPlaying())
203 .WillOnce(SignalEvent(&play_event_
));
206 EXPECT_CALL(mock_stream_
, Close());
208 controller_
->StopDiverting();
211 void SwitchDevice(bool diverting
) {
213 // Expect the current stream to close and a new stream to start
214 // playing if not diverting. When diverting, nothing happens
215 // until diverting is stopped.
216 EXPECT_CALL(mock_event_handler_
, OnPlaying())
217 .WillOnce(SignalEvent(&play_event_
));
220 controller_
->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName
,
221 base::Bind(&base::DoNothing
));
225 EXPECT_CALL(mock_sync_reader_
, Close());
227 controller_
->Close(base::MessageLoop::QuitClosure());
228 base::MessageLoop::current()->Run();
231 // These help make test sequences more readable.
232 void DivertNeverPlaying() { Divert(false, 0); }
233 void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); }
234 void DivertWhilePlaying() { Divert(true, 1); }
235 void RevertWasNotPlaying() { Revert(false); }
236 void RevertWhilePlaying() { Revert(true); }
238 // These synchronize the main thread with key events taking place on other
240 void WaitForCreate() { create_event_
.Wait(); }
241 void WaitForPlay() { play_event_
.Wait(); }
242 void WaitForReads() {
243 // Note: Arbitrarily chosen, but more iterations causes tests to take
244 // significantly more time.
245 static const int kNumIterations
= 3;
246 for (int i
= 0; i
< kNumIterations
; ++i
) {
250 void WaitForPause() { pause_event_
.Wait(); }
253 base::MessageLoopForIO message_loop_
;
254 scoped_ptr
<AudioManager
> audio_manager_
;
255 MockAudioOutputControllerEventHandler mock_event_handler_
;
256 MockAudioOutputControllerSyncReader mock_sync_reader_
;
257 MockAudioOutputStream mock_stream_
;
258 base::WaitableEvent create_event_
;
259 base::WaitableEvent play_event_
;
260 base::WaitableEvent read_event_
;
261 base::WaitableEvent pause_event_
;
262 AudioParameters params_
;
263 scoped_refptr
<AudioOutputController
> controller_
;
265 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest
);
268 TEST_F(AudioOutputControllerTest
, CreateAndClose
) {
269 Create(kSamplesPerPacket
);
273 TEST_F(AudioOutputControllerTest
, HardwareBufferTooLarge
) {
274 Create(kSamplesPerPacket
* 1000);
277 TEST_F(AudioOutputControllerTest
, PlayAndClose
) {
278 Create(kSamplesPerPacket
);
286 TEST_F(AudioOutputControllerTest
, PlayPauseClose
) {
287 Create(kSamplesPerPacket
);
297 TEST_F(AudioOutputControllerTest
, PlayPausePlayClose
) {
298 Create(kSamplesPerPacket
);
310 TEST_F(AudioOutputControllerTest
, PlayDeviceChangeClose
) {
311 Create(kSamplesPerPacket
);
322 TEST_F(AudioOutputControllerTest
, PlaySwitchDeviceClose
) {
323 Create(kSamplesPerPacket
);
334 TEST_F(AudioOutputControllerTest
, PlayDivertRevertClose
) {
335 Create(kSamplesPerPacket
);
340 DivertWhilePlaying();
342 ReadDivertedAudioData();
343 RevertWhilePlaying();
349 TEST_F(AudioOutputControllerTest
, PlayDivertSwitchDeviceRevertClose
) {
350 Create(kSamplesPerPacket
);
355 DivertWhilePlaying();
358 ReadDivertedAudioData();
359 RevertWhilePlaying();
365 TEST_F(AudioOutputControllerTest
, PlayDivertRevertDivertRevertClose
) {
366 Create(kSamplesPerPacket
);
371 DivertWhilePlaying();
373 ReadDivertedAudioData();
374 RevertWhilePlaying();
377 DivertWhilePlaying();
379 ReadDivertedAudioData();
380 RevertWhilePlaying();
386 TEST_F(AudioOutputControllerTest
, DivertPlayPausePlayRevertClose
) {
387 Create(kSamplesPerPacket
);
389 DivertWillEventuallyBeTwicePlayed();
392 ReadDivertedAudioData();
397 ReadDivertedAudioData();
398 RevertWhilePlaying();
404 TEST_F(AudioOutputControllerTest
, DivertRevertClose
) {
405 Create(kSamplesPerPacket
);
407 DivertNeverPlaying();
408 RevertWasNotPlaying();