audio_output_controller_unittest.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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 double kTestVolume = 0.25; 33 34class MockAudioOutputControllerEventHandler 35 : public AudioOutputController::EventHandler { 36 public: 37 MockAudioOutputControllerEventHandler() {} 38 39 MOCK_METHOD0(OnCreated, void()); 40 MOCK_METHOD0(OnPlaying, void()); 41 MOCK_METHOD2(OnPowerMeasured, void(float power_dbfs, bool clipped)); 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_METHOD3(Read, int(bool block, const AudioBus* source, 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 arg2->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 arg2->channel(0)[0] = kBufferNonZeroData; 90} 91 92class AudioOutputControllerTest : public testing::Test { 93 public: 94 AudioOutputControllerTest() 95 : audio_manager_(AudioManager::Create()), 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 std::string(), &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 and one or more 132 // OnPowerMeasured() calls. 133 EXPECT_CALL(mock_event_handler_, OnPlaying()) 134 .WillOnce(SignalEvent(&play_event_)); 135 EXPECT_CALL(mock_event_handler_, OnPowerMeasured(_, false)) 136 .Times(AtLeast(1)); 137 138 // During playback, the mock pretends to provide audio data rendered and 139 // sent from the render process. 140 EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_)) 141 .Times(AtLeast(1)); 142 EXPECT_CALL(mock_sync_reader_, Read(_, _, _)) 143 .WillRepeatedly(DoAll(PopulateBuffer(), 144 SignalEvent(&read_event_), 145 Return(params_.frames_per_buffer()))); 146 controller_->Play(); 147 } 148 149 void Pause() { 150 // Expect the event handler to receive one OnPaused() call. 151 EXPECT_CALL(mock_event_handler_, OnPaused()) 152 .WillOnce(SignalEvent(&pause_event_)); 153 154 controller_->Pause(); 155 } 156 157 void ChangeDevice() { 158 // Expect the event handler to receive one OnPaying() call and no OnPaused() 159 // call. 160 EXPECT_CALL(mock_event_handler_, OnPlaying()) 161 .WillOnce(SignalEvent(&play_event_)); 162 EXPECT_CALL(mock_event_handler_, OnPaused()) 163 .Times(0); 164 165 // Simulate a device change event to AudioOutputController from the 166 // AudioManager. 167 audio_manager_->GetMessageLoop()->PostTask( 168 FROM_HERE, 169 base::Bind(&AudioOutputController::OnDeviceChange, controller_)); 170 } 171 172 void Divert(bool was_playing, int num_times_to_be_started) { 173 if (was_playing) { 174 // Expect the handler to receive one OnPlaying() call as a result of the 175 // stream switching. 176 EXPECT_CALL(mock_event_handler_, OnPlaying()) 177 .WillOnce(SignalEvent(&play_event_)); 178 } 179 180 EXPECT_CALL(mock_stream_, Open()) 181 .WillOnce(Return(true)); 182 EXPECT_CALL(mock_stream_, SetVolume(kTestVolume)); 183 if (num_times_to_be_started > 0) { 184 EXPECT_CALL(mock_stream_, Start(NotNull())) 185 .Times(num_times_to_be_started) 186 .WillRepeatedly( 187 Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback)); 188 EXPECT_CALL(mock_stream_, Stop()) 189 .Times(num_times_to_be_started); 190 } 191 192 controller_->StartDiverting(&mock_stream_); 193 } 194 195 void ReadDivertedAudioData() { 196 scoped_ptr<AudioBus> dest = AudioBus::Create(params_); 197 ASSERT_TRUE(!!mock_stream_.callback()); 198 const int frames_read = 199 mock_stream_.callback()->OnMoreData(dest.get(), AudioBuffersState()); 200 EXPECT_LT(0, frames_read); 201 EXPECT_EQ(kBufferNonZeroData, dest->channel(0)[0]); 202 } 203 204 void Revert(bool was_playing) { 205 if (was_playing) { 206 // Expect the handler to receive one OnPlaying() call as a result of the 207 // stream switching back. 208 EXPECT_CALL(mock_event_handler_, OnPlaying()) 209 .WillOnce(SignalEvent(&play_event_)); 210 } 211 212 EXPECT_CALL(mock_stream_, Close()); 213 214 controller_->StopDiverting(); 215 } 216 217 void Close() { 218 EXPECT_CALL(mock_sync_reader_, Close()); 219 220 controller_->Close(base::MessageLoop::QuitClosure()); 221 base::MessageLoop::current()->Run(); 222 } 223 224 // These help make test sequences more readable. 225 void DivertNeverPlaying() { Divert(false, 0); } 226 void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); } 227 void DivertWhilePlaying() { Divert(true, 1); } 228 void RevertWasNotPlaying() { Revert(false); } 229 void RevertWhilePlaying() { Revert(true); } 230 231 // These synchronize the main thread with key events taking place on other 232 // threads. 233 void WaitForCreate() { create_event_.Wait(); } 234 void WaitForPlay() { play_event_.Wait(); } 235 void WaitForReads() { 236 // Note: Arbitrarily chosen, but more iterations causes tests to take 237 // significantly more time. 238 static const int kNumIterations = 3; 239 for (int i = 0; i < kNumIterations; ++i) { 240 read_event_.Wait(); 241 } 242 } 243 void WaitForPause() { pause_event_.Wait(); } 244 245 private: 246 base::MessageLoopForIO message_loop_; 247 scoped_ptr<AudioManager> audio_manager_; 248 MockAudioOutputControllerEventHandler mock_event_handler_; 249 MockAudioOutputControllerSyncReader mock_sync_reader_; 250 MockAudioOutputStream mock_stream_; 251 base::WaitableEvent create_event_; 252 base::WaitableEvent play_event_; 253 base::WaitableEvent read_event_; 254 base::WaitableEvent pause_event_; 255 AudioParameters params_; 256 scoped_refptr<AudioOutputController> controller_; 257 258 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest); 259}; 260 261TEST_F(AudioOutputControllerTest, CreateAndClose) { 262 Create(kSamplesPerPacket); 263 Close(); 264} 265 266TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) { 267 Create(kSamplesPerPacket * 1000); 268} 269 270TEST_F(AudioOutputControllerTest, PlayAndClose) { 271 Create(kSamplesPerPacket); 272 WaitForCreate(); 273 Play(); 274 WaitForPlay(); 275 WaitForReads(); 276 Close(); 277} 278 279TEST_F(AudioOutputControllerTest, PlayPauseClose) { 280 Create(kSamplesPerPacket); 281 WaitForCreate(); 282 Play(); 283 WaitForPlay(); 284 WaitForReads(); 285 Pause(); 286 WaitForPause(); 287 Close(); 288} 289 290TEST_F(AudioOutputControllerTest, PlayPausePlayClose) { 291 Create(kSamplesPerPacket); 292 WaitForCreate(); 293 Play(); 294 WaitForPlay(); 295 WaitForReads(); 296 Pause(); 297 WaitForPause(); 298 Play(); 299 WaitForPlay(); 300 Close(); 301} 302 303TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) { 304 Create(kSamplesPerPacket); 305 WaitForCreate(); 306 Play(); 307 WaitForPlay(); 308 WaitForReads(); 309 ChangeDevice(); 310 WaitForPlay(); 311 WaitForReads(); 312 Close(); 313} 314 315TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) { 316 Create(kSamplesPerPacket); 317 WaitForCreate(); 318 Play(); 319 WaitForPlay(); 320 WaitForReads(); 321 DivertWhilePlaying(); 322 WaitForPlay(); 323 ReadDivertedAudioData(); 324 RevertWhilePlaying(); 325 WaitForPlay(); 326 WaitForReads(); 327 Close(); 328} 329 330TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) { 331 Create(kSamplesPerPacket); 332 WaitForCreate(); 333 Play(); 334 WaitForPlay(); 335 WaitForReads(); 336 DivertWhilePlaying(); 337 WaitForPlay(); 338 ReadDivertedAudioData(); 339 RevertWhilePlaying(); 340 WaitForPlay(); 341 WaitForReads(); 342 DivertWhilePlaying(); 343 WaitForPlay(); 344 ReadDivertedAudioData(); 345 RevertWhilePlaying(); 346 WaitForPlay(); 347 WaitForReads(); 348 Close(); 349} 350 351TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) { 352 Create(kSamplesPerPacket); 353 WaitForCreate(); 354 DivertWillEventuallyBeTwicePlayed(); 355 Play(); 356 WaitForPlay(); 357 ReadDivertedAudioData(); 358 Pause(); 359 WaitForPause(); 360 Play(); 361 WaitForPlay(); 362 ReadDivertedAudioData(); 363 RevertWhilePlaying(); 364 WaitForPlay(); 365 WaitForReads(); 366 Close(); 367} 368 369TEST_F(AudioOutputControllerTest, DivertRevertClose) { 370 Create(kSamplesPerPacket); 371 WaitForCreate(); 372 DivertNeverPlaying(); 373 RevertWasNotPlaying(); 374 Close(); 375} 376 377} // namespace media 378