audio_output_controller_unittest.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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_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" 18 19using ::testing::_; 20using ::testing::AtLeast; 21using ::testing::DoAll; 22using ::testing::Invoke; 23using ::testing::NotNull; 24using ::testing::Return; 25 26namespace media { 27 28static const int kSampleRate = AudioParameters::kAudioCDSampleRate; 29static const int kBitsPerSample = 16; 30static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 31static const int kSamplesPerPacket = kSampleRate / 100; 32static const int kHardwareBufferSize = kSamplesPerPacket * 33 ChannelLayoutToChannelCount(kChannelLayout) * kBitsPerSample / 8; 34static const double kTestVolume = 0.25; 35 36class MockAudioOutputControllerEventHandler 37 : public AudioOutputController::EventHandler { 38 public: 39 MockAudioOutputControllerEventHandler() {} 40 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)); 47 48 private: 49 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler); 50}; 51 52class MockAudioOutputControllerSyncReader 53 : public AudioOutputController::SyncReader { 54 public: 55 MockAudioOutputControllerSyncReader() {} 56 57 MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes)); 58 MOCK_METHOD3(Read, int(bool block, const AudioBus* source, AudioBus* dest)); 59 MOCK_METHOD0(Close, void()); 60 61 private: 62 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader); 63}; 64 65class MockAudioOutputStream : public AudioOutputStream { 66 public: 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()); 73 74 // Set/get the callback passed to Start(). 75 AudioSourceCallback* callback() const { return callback_; } 76 void SetCallback(AudioSourceCallback* asc) { callback_ = asc; } 77 78 private: 79 AudioSourceCallback* callback_; 80}; 81 82ACTION_P(SignalEvent, event) { 83 event->Signal(); 84} 85 86static const float kBufferNonZeroData = 1.0f; 87ACTION(PopulateBuffer) { 88 arg2->Zero(); 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; 92} 93 94class AudioOutputControllerTest : public testing::Test { 95 public: 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) { 102 } 103 104 virtual ~AudioOutputControllerTest() { 105 } 106 107 protected: 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()); 113 114 params_ = AudioParameters( 115 AudioParameters::AUDIO_FAKE, kChannelLayout, 116 kSampleRate, kBitsPerSample, samples_per_packet); 117 118 if (params_.IsValid()) { 119 EXPECT_CALL(mock_event_handler_, OnCreated()) 120 .WillOnce(SignalEvent(&create_event_)); 121 } 122 123 controller_ = AudioOutputController::Create( 124 audio_manager_.get(), &mock_event_handler_, params_, std::string(), 125 &mock_sync_reader_); 126 if (controller_.get()) 127 controller_->SetVolume(kTestVolume); 128 129 EXPECT_EQ(params_.IsValid(), controller_.get() != NULL); 130 } 131 132 void Play() { 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)) 138 .Times(AtLeast(1)); 139 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(_)) 143 .Times(AtLeast(1)); 144 EXPECT_CALL(mock_sync_reader_, Read(_, _, _)) 145 .WillRepeatedly(DoAll(PopulateBuffer(), 146 SignalEvent(&read_event_), 147 Return(params_.frames_per_buffer()))); 148 controller_->Play(); 149 } 150 151 void Pause() { 152 // Expect the event handler to receive one OnPaused() call. 153 EXPECT_CALL(mock_event_handler_, OnPaused()) 154 .WillOnce(SignalEvent(&pause_event_)); 155 156 controller_->Pause(); 157 } 158 159 void ChangeDevice() { 160 // Expect the event handler to receive one OnPaying() call and no OnPaused() 161 // call. 162 EXPECT_CALL(mock_event_handler_, OnPlaying()) 163 .WillOnce(SignalEvent(&play_event_)); 164 EXPECT_CALL(mock_event_handler_, OnPaused()) 165 .Times(0); 166 167 // Simulate a device change event to AudioOutputController from the 168 // AudioManager. 169 audio_manager_->GetMessageLoop()->PostTask( 170 FROM_HERE, 171 base::Bind(&AudioOutputController::OnDeviceChange, controller_)); 172 } 173 174 void Divert(bool was_playing, int num_times_to_be_started) { 175 if (was_playing) { 176 // Expect the handler to receive one OnPlaying() call as a result of the 177 // stream switching. 178 EXPECT_CALL(mock_event_handler_, OnPlaying()) 179 .WillOnce(SignalEvent(&play_event_)); 180 } 181 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) 188 .WillRepeatedly( 189 Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback)); 190 EXPECT_CALL(mock_stream_, Stop()) 191 .Times(num_times_to_be_started); 192 } 193 194 controller_->StartDiverting(&mock_stream_); 195 } 196 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]); 204 } 205 206 void Revert(bool was_playing) { 207 if (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_)); 212 } 213 214 EXPECT_CALL(mock_stream_, Close()); 215 216 controller_->StopDiverting(); 217 } 218 219 void Close() { 220 EXPECT_CALL(mock_sync_reader_, Close()); 221 222 controller_->Close(base::MessageLoop::QuitClosure()); 223 base::MessageLoop::current()->Run(); 224 } 225 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); } 232 233 // These synchronize the main thread with key events taking place on other 234 // threads. 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) { 242 read_event_.Wait(); 243 } 244 } 245 void WaitForPause() { pause_event_.Wait(); } 246 247 private: 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_; 259 260 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest); 261}; 262 263TEST_F(AudioOutputControllerTest, CreateAndClose) { 264 Create(kSamplesPerPacket); 265 Close(); 266} 267 268TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) { 269 Create(kSamplesPerPacket * 1000); 270} 271 272TEST_F(AudioOutputControllerTest, PlayAndClose) { 273 Create(kSamplesPerPacket); 274 WaitForCreate(); 275 Play(); 276 WaitForPlay(); 277 WaitForReads(); 278 Close(); 279} 280 281TEST_F(AudioOutputControllerTest, PlayPauseClose) { 282 Create(kSamplesPerPacket); 283 WaitForCreate(); 284 Play(); 285 WaitForPlay(); 286 WaitForReads(); 287 Pause(); 288 WaitForPause(); 289 Close(); 290} 291 292TEST_F(AudioOutputControllerTest, PlayPausePlayClose) { 293 Create(kSamplesPerPacket); 294 WaitForCreate(); 295 Play(); 296 WaitForPlay(); 297 WaitForReads(); 298 Pause(); 299 WaitForPause(); 300 Play(); 301 WaitForPlay(); 302 Close(); 303} 304 305TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) { 306 Create(kSamplesPerPacket); 307 WaitForCreate(); 308 Play(); 309 WaitForPlay(); 310 WaitForReads(); 311 ChangeDevice(); 312 WaitForPlay(); 313 WaitForReads(); 314 Close(); 315} 316 317TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) { 318 Create(kSamplesPerPacket); 319 WaitForCreate(); 320 Play(); 321 WaitForPlay(); 322 WaitForReads(); 323 DivertWhilePlaying(); 324 WaitForPlay(); 325 ReadDivertedAudioData(); 326 RevertWhilePlaying(); 327 WaitForPlay(); 328 WaitForReads(); 329 Close(); 330} 331 332TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) { 333 Create(kSamplesPerPacket); 334 WaitForCreate(); 335 Play(); 336 WaitForPlay(); 337 WaitForReads(); 338 DivertWhilePlaying(); 339 WaitForPlay(); 340 ReadDivertedAudioData(); 341 RevertWhilePlaying(); 342 WaitForPlay(); 343 WaitForReads(); 344 DivertWhilePlaying(); 345 WaitForPlay(); 346 ReadDivertedAudioData(); 347 RevertWhilePlaying(); 348 WaitForPlay(); 349 WaitForReads(); 350 Close(); 351} 352 353TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) { 354 Create(kSamplesPerPacket); 355 WaitForCreate(); 356 DivertWillEventuallyBeTwicePlayed(); 357 Play(); 358 WaitForPlay(); 359 ReadDivertedAudioData(); 360 Pause(); 361 WaitForPause(); 362 Play(); 363 WaitForPlay(); 364 ReadDivertedAudioData(); 365 RevertWhilePlaying(); 366 WaitForPlay(); 367 WaitForReads(); 368 Close(); 369} 370 371TEST_F(AudioOutputControllerTest, DivertRevertClose) { 372 Create(kSamplesPerPacket); 373 WaitForCreate(); 374 DivertNeverPlaying(); 375 RevertWasNotPlaying(); 376 Close(); 377} 378 379} // namespace media 380