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());
44 MOCK_METHOD2(OnDeviceChange
, void(int new_buffer_size
, int new_sample_rate
));
47 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler
);
50 class MockAudioOutputControllerSyncReader
51 : public AudioOutputController::SyncReader
{
53 MockAudioOutputControllerSyncReader() {}
55 MOCK_METHOD1(UpdatePendingBytes
, void(uint32 bytes
));
56 MOCK_METHOD2(Read
, void(const AudioBus
* source
, AudioBus
* dest
));
57 MOCK_METHOD0(Close
, void());
60 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader
);
63 class MockAudioOutputStream
: public AudioOutputStream
{
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());
72 // Set/get the callback passed to Start().
73 AudioSourceCallback
* callback() const { return callback_
; }
74 void SetCallback(AudioSourceCallback
* asc
) { callback_
= asc
; }
77 AudioSourceCallback
* callback_
;
80 ACTION_P(SignalEvent
, event
) {
84 static const float kBufferNonZeroData
= 1.0f
;
85 ACTION(PopulateBuffer
) {
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 arg1
->channel(0)[0] = kBufferNonZeroData
;
92 class AudioOutputControllerTest
: public testing::Test
{
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) {
102 virtual ~AudioOutputControllerTest() {
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());
112 params_
= AudioParameters(
113 AudioParameters::AUDIO_FAKE
, kChannelLayout
,
114 kSampleRate
, kBitsPerSample
, samples_per_packet
);
116 if (params_
.IsValid()) {
117 EXPECT_CALL(mock_event_handler_
, OnCreated())
118 .WillOnce(SignalEvent(&create_event_
));
121 controller_
= AudioOutputController::Create(
122 audio_manager_
.get(), &mock_event_handler_
, params_
, std::string(),
124 if (controller_
.get())
125 controller_
->SetVolume(kTestVolume
);
127 EXPECT_EQ(params_
.IsValid(), controller_
.get() != NULL
);
131 // Expect the event handler to receive one OnPlaying() call.
132 EXPECT_CALL(mock_event_handler_
, OnPlaying())
133 .WillOnce(SignalEvent(&play_event_
));
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(_
))
139 EXPECT_CALL(mock_sync_reader_
, Read(_
, _
))
140 .WillRepeatedly(DoAll(PopulateBuffer(),
141 SignalEvent(&read_event_
)));
146 // Expect the event handler to receive one OnPaused() call.
147 EXPECT_CALL(mock_event_handler_
, OnPaused())
148 .WillOnce(SignalEvent(&pause_event_
));
150 controller_
->Pause();
153 void ChangeDevice() {
154 // Expect the event handler to receive one OnPaying() call and no OnPaused()
156 EXPECT_CALL(mock_event_handler_
, OnPlaying())
157 .WillOnce(SignalEvent(&play_event_
));
158 EXPECT_CALL(mock_event_handler_
, OnPaused())
161 // Simulate a device change event to AudioOutputController from the
163 audio_manager_
->GetTaskRunner()->PostTask(
165 base::Bind(&AudioOutputController::OnDeviceChange
, controller_
));
168 void Divert(bool was_playing
, int num_times_to_be_started
) {
170 // Expect the handler to receive one OnPlaying() call as a result of the
172 EXPECT_CALL(mock_event_handler_
, OnPlaying())
173 .WillOnce(SignalEvent(&play_event_
));
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
)
183 Invoke(&mock_stream_
, &MockAudioOutputStream::SetCallback
));
184 EXPECT_CALL(mock_stream_
, Stop())
185 .Times(num_times_to_be_started
);
188 controller_
->StartDiverting(&mock_stream_
);
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]);
200 void Revert(bool 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_
));
208 EXPECT_CALL(mock_stream_
, Close());
210 controller_
->StopDiverting();
213 void SwitchDevice(bool 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_
));
222 controller_
->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName
,
223 base::Bind(&base::DoNothing
));
227 EXPECT_CALL(mock_sync_reader_
, Close());
229 controller_
->Close(base::MessageLoop::QuitClosure());
230 base::MessageLoop::current()->Run();
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); }
240 // These synchronize the main thread with key events taking place on other
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
) {
252 void WaitForPause() { pause_event_
.Wait(); }
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_
;
267 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest
);
270 TEST_F(AudioOutputControllerTest
, CreateAndClose
) {
271 Create(kSamplesPerPacket
);
275 TEST_F(AudioOutputControllerTest
, HardwareBufferTooLarge
) {
276 Create(kSamplesPerPacket
* 1000);
279 TEST_F(AudioOutputControllerTest
, PlayAndClose
) {
280 Create(kSamplesPerPacket
);
288 TEST_F(AudioOutputControllerTest
, PlayPauseClose
) {
289 Create(kSamplesPerPacket
);
299 TEST_F(AudioOutputControllerTest
, PlayPausePlayClose
) {
300 Create(kSamplesPerPacket
);
312 TEST_F(AudioOutputControllerTest
, PlayDeviceChangeClose
) {
313 Create(kSamplesPerPacket
);
324 TEST_F(AudioOutputControllerTest
, PlaySwitchDeviceClose
) {
325 Create(kSamplesPerPacket
);
336 TEST_F(AudioOutputControllerTest
, PlayDivertRevertClose
) {
337 Create(kSamplesPerPacket
);
342 DivertWhilePlaying();
344 ReadDivertedAudioData();
345 RevertWhilePlaying();
351 TEST_F(AudioOutputControllerTest
, PlayDivertSwitchDeviceRevertClose
) {
352 Create(kSamplesPerPacket
);
357 DivertWhilePlaying();
360 ReadDivertedAudioData();
361 RevertWhilePlaying();
367 TEST_F(AudioOutputControllerTest
, PlayDivertRevertDivertRevertClose
) {
368 Create(kSamplesPerPacket
);
373 DivertWhilePlaying();
375 ReadDivertedAudioData();
376 RevertWhilePlaying();
379 DivertWhilePlaying();
381 ReadDivertedAudioData();
382 RevertWhilePlaying();
388 TEST_F(AudioOutputControllerTest
, DivertPlayPausePlayRevertClose
) {
389 Create(kSamplesPerPacket
);
391 DivertWillEventuallyBeTwicePlayed();
394 ReadDivertedAudioData();
399 ReadDivertedAudioData();
400 RevertWhilePlaying();
406 TEST_F(AudioOutputControllerTest
, DivertRevertClose
) {
407 Create(kSamplesPerPacket
);
409 DivertNeverPlaying();
410 RevertWasNotPlaying();