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. 4 5#include "base/basictypes.h" 6#include "base/bind.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" 19 20using ::testing::_; 21using ::testing::AtLeast; 22using ::testing::DoAll; 23using ::testing::Invoke; 24using ::testing::NotNull; 25using ::testing::Return; 26 27namespace media { 28 29static const int kSampleRate = AudioParameters::kAudioCDSampleRate; 30static const int kBitsPerSample = 16; 31static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 32static const int kSamplesPerPacket = kSampleRate / 100; 33static const double kTestVolume = 0.25; 34 35class MockAudioOutputControllerEventHandler 36 : public AudioOutputController::EventHandler { 37 public: 38 MockAudioOutputControllerEventHandler() {} 39 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)); 45 46 private: 47 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler); 48}; 49 50class MockAudioOutputControllerSyncReader 51 : public AudioOutputController::SyncReader { 52 public: 53 MockAudioOutputControllerSyncReader() {} 54 55 MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes)); 56 MOCK_METHOD1(Read, void(AudioBus* dest)); 57 MOCK_METHOD0(Close, void()); 58 59 private: 60 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader); 61}; 62 63class MockAudioOutputStream : public AudioOutputStream { 64 public: 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()); 71 72 // Set/get the callback passed to Start(). 73 AudioSourceCallback* callback() const { return callback_; } 74 void SetCallback(AudioSourceCallback* asc) { callback_ = asc; } 75 76 private: 77 AudioSourceCallback* callback_; 78}; 79 80ACTION_P(SignalEvent, event) { 81 event->Signal(); 82} 83 84static const float kBufferNonZeroData = 1.0f; 85ACTION(PopulateBuffer) { 86 arg0->Zero(); 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 arg0->channel(0)[0] = kBufferNonZeroData; 90} 91 92class AudioOutputControllerTest : public testing::Test { 93 public: 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) { 100 } 101 102 virtual ~AudioOutputControllerTest() { 103 } 104 105 protected: 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()); 111 112 params_ = AudioParameters( 113 AudioParameters::AUDIO_FAKE, kChannelLayout, 114 kSampleRate, kBitsPerSample, samples_per_packet); 115 116 if (params_.IsValid()) { 117 EXPECT_CALL(mock_event_handler_, OnCreated()) 118 .WillOnce(SignalEvent(&create_event_)); 119 } 120 121 controller_ = AudioOutputController::Create( 122 audio_manager_.get(), &mock_event_handler_, params_, std::string(), 123 &mock_sync_reader_); 124 if (controller_.get()) 125 controller_->SetVolume(kTestVolume); 126 127 EXPECT_EQ(params_.IsValid(), controller_.get() != NULL); 128 } 129 130 void Play() { 131 // Expect the event handler to receive one OnPlaying() call. 132 EXPECT_CALL(mock_event_handler_, OnPlaying()) 133 .WillOnce(SignalEvent(&play_event_)); 134 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(_)) 138 .Times(AtLeast(1)); 139 EXPECT_CALL(mock_sync_reader_, Read(_)) 140 .WillRepeatedly(DoAll(PopulateBuffer(), 141 SignalEvent(&read_event_))); 142 controller_->Play(); 143 } 144 145 void Pause() { 146 // Expect the event handler to receive one OnPaused() call. 147 EXPECT_CALL(mock_event_handler_, OnPaused()) 148 .WillOnce(SignalEvent(&pause_event_)); 149 150 controller_->Pause(); 151 } 152 153 void ChangeDevice() { 154 // Expect the event handler to receive one OnPaying() call and no OnPaused() 155 // call. 156 EXPECT_CALL(mock_event_handler_, OnPlaying()) 157 .WillOnce(SignalEvent(&play_event_)); 158 EXPECT_CALL(mock_event_handler_, OnPaused()) 159 .Times(0); 160 161 // Simulate a device change event to AudioOutputController from the 162 // AudioManager. 163 audio_manager_->GetTaskRunner()->PostTask( 164 FROM_HERE, 165 base::Bind(&AudioOutputController::OnDeviceChange, controller_)); 166 } 167 168 void Divert(bool was_playing, int num_times_to_be_started) { 169 if (was_playing) { 170 // Expect the handler to receive one OnPlaying() call as a result of the 171 // stream switching. 172 EXPECT_CALL(mock_event_handler_, OnPlaying()) 173 .WillOnce(SignalEvent(&play_event_)); 174 } 175 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) 182 .WillRepeatedly( 183 Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback)); 184 EXPECT_CALL(mock_stream_, Stop()) 185 .Times(num_times_to_be_started); 186 } 187 188 controller_->StartDiverting(&mock_stream_); 189 } 190 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]); 198 } 199 200 void Revert(bool was_playing) { 201 if (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_)); 206 } 207 208 EXPECT_CALL(mock_stream_, Close()); 209 210 controller_->StopDiverting(); 211 } 212 213 void SwitchDevice(bool diverting) { 214 if (!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_)); 220 } 221 222 controller_->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName, 223 base::Bind(&base::DoNothing)); 224 } 225 226 void Close() { 227 EXPECT_CALL(mock_sync_reader_, Close()); 228 229 controller_->Close(base::MessageLoop::QuitClosure()); 230 base::MessageLoop::current()->Run(); 231 } 232 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); } 239 240 // These synchronize the main thread with key events taking place on other 241 // threads. 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) { 249 read_event_.Wait(); 250 } 251 } 252 void WaitForPause() { pause_event_.Wait(); } 253 254 private: 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_; 266 267 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest); 268}; 269 270TEST_F(AudioOutputControllerTest, CreateAndClose) { 271 Create(kSamplesPerPacket); 272 Close(); 273} 274 275TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) { 276 Create(kSamplesPerPacket * 1000); 277} 278 279TEST_F(AudioOutputControllerTest, PlayAndClose) { 280 Create(kSamplesPerPacket); 281 WaitForCreate(); 282 Play(); 283 WaitForPlay(); 284 WaitForReads(); 285 Close(); 286} 287 288TEST_F(AudioOutputControllerTest, PlayPauseClose) { 289 Create(kSamplesPerPacket); 290 WaitForCreate(); 291 Play(); 292 WaitForPlay(); 293 WaitForReads(); 294 Pause(); 295 WaitForPause(); 296 Close(); 297} 298 299TEST_F(AudioOutputControllerTest, PlayPausePlayClose) { 300 Create(kSamplesPerPacket); 301 WaitForCreate(); 302 Play(); 303 WaitForPlay(); 304 WaitForReads(); 305 Pause(); 306 WaitForPause(); 307 Play(); 308 WaitForPlay(); 309 Close(); 310} 311 312TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) { 313 Create(kSamplesPerPacket); 314 WaitForCreate(); 315 Play(); 316 WaitForPlay(); 317 WaitForReads(); 318 ChangeDevice(); 319 WaitForPlay(); 320 WaitForReads(); 321 Close(); 322} 323 324TEST_F(AudioOutputControllerTest, PlaySwitchDeviceClose) { 325 Create(kSamplesPerPacket); 326 WaitForCreate(); 327 Play(); 328 WaitForPlay(); 329 WaitForReads(); 330 SwitchDevice(false); 331 WaitForPlay(); 332 WaitForReads(); 333 Close(); 334} 335 336TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) { 337 Create(kSamplesPerPacket); 338 WaitForCreate(); 339 Play(); 340 WaitForPlay(); 341 WaitForReads(); 342 DivertWhilePlaying(); 343 WaitForPlay(); 344 ReadDivertedAudioData(); 345 RevertWhilePlaying(); 346 WaitForPlay(); 347 WaitForReads(); 348 Close(); 349} 350 351TEST_F(AudioOutputControllerTest, PlayDivertSwitchDeviceRevertClose) { 352 Create(kSamplesPerPacket); 353 WaitForCreate(); 354 Play(); 355 WaitForPlay(); 356 WaitForReads(); 357 DivertWhilePlaying(); 358 WaitForPlay(); 359 SwitchDevice(true); 360 ReadDivertedAudioData(); 361 RevertWhilePlaying(); 362 WaitForPlay(); 363 WaitForReads(); 364 Close(); 365} 366 367TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) { 368 Create(kSamplesPerPacket); 369 WaitForCreate(); 370 Play(); 371 WaitForPlay(); 372 WaitForReads(); 373 DivertWhilePlaying(); 374 WaitForPlay(); 375 ReadDivertedAudioData(); 376 RevertWhilePlaying(); 377 WaitForPlay(); 378 WaitForReads(); 379 DivertWhilePlaying(); 380 WaitForPlay(); 381 ReadDivertedAudioData(); 382 RevertWhilePlaying(); 383 WaitForPlay(); 384 WaitForReads(); 385 Close(); 386} 387 388TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) { 389 Create(kSamplesPerPacket); 390 WaitForCreate(); 391 DivertWillEventuallyBeTwicePlayed(); 392 Play(); 393 WaitForPlay(); 394 ReadDivertedAudioData(); 395 Pause(); 396 WaitForPause(); 397 Play(); 398 WaitForPlay(); 399 ReadDivertedAudioData(); 400 RevertWhilePlaying(); 401 WaitForPlay(); 402 WaitForReads(); 403 Close(); 404} 405 406TEST_F(AudioOutputControllerTest, DivertRevertClose) { 407 Create(kSamplesPerPacket); 408 WaitForCreate(); 409 DivertNeverPlaying(); 410 RevertWasNotPlaying(); 411 Close(); 412} 413 414} // namespace media 415