| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
| 8 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
| 9 #include "base/run_loop.h" |
| 9 #include "media/audio/audio_manager.h" | 10 #include "media/audio/audio_manager.h" |
| 10 #include "media/audio/audio_manager_base.h" | 11 #include "media/audio/audio_manager_base.h" |
| 11 #include "media/audio/audio_output_dispatcher_impl.h" | 12 #include "media/audio/audio_output_dispatcher_impl.h" |
| 12 #include "media/audio/audio_output_proxy.h" | 13 #include "media/audio/audio_output_proxy.h" |
| 13 #include "media/audio/audio_output_resampler.h" | 14 #include "media/audio/audio_output_resampler.h" |
| 14 #include "media/audio/fake_audio_log_factory.h" | 15 #include "media/audio/fake_audio_log_factory.h" |
| 15 #include "media/audio/fake_audio_output_stream.h" | 16 #include "media/audio/fake_audio_output_stream.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 19 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 30 using media::AudioManager; | 31 using media::AudioManager; |
| 31 using media::AudioManagerBase; | 32 using media::AudioManagerBase; |
| 32 using media::AudioOutputDispatcher; | 33 using media::AudioOutputDispatcher; |
| 33 using media::AudioOutputProxy; | 34 using media::AudioOutputProxy; |
| 34 using media::AudioOutputStream; | 35 using media::AudioOutputStream; |
| 35 using media::AudioParameters; | 36 using media::AudioParameters; |
| 36 using media::FakeAudioOutputStream; | 37 using media::FakeAudioOutputStream; |
| 37 | 38 |
| 38 namespace { | 39 namespace { |
| 39 | 40 |
| 40 static const int kTestCloseDelayMs = 100; | 41 static const int kTestCloseDelayMs = 10; |
| 41 | |
| 42 // Used in the test where we don't want a stream to be closed unexpectedly. | |
| 43 static const int kTestBigCloseDelaySeconds = 1000; | |
| 44 | 42 |
| 45 // Delay between callbacks to AudioSourceCallback::OnMoreData. | 43 // Delay between callbacks to AudioSourceCallback::OnMoreData. |
| 46 static const int kOnMoreDataCallbackDelayMs = 10; | 44 static const int kOnMoreDataCallbackDelayMs = 10; |
| 47 | 45 |
| 48 // Let start run long enough for many OnMoreData callbacks to occur. | 46 // Let start run long enough for many OnMoreData callbacks to occur. |
| 49 static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10; | 47 static const int kStartRunTimeMs = kOnMoreDataCallbackDelayMs * 10; |
| 50 | 48 |
| 51 class MockAudioOutputStream : public AudioOutputStream { | 49 class MockAudioOutputStream : public AudioOutputStream { |
| 52 public: | 50 public: |
| 53 MockAudioOutputStream(AudioManagerBase* manager, | 51 MockAudioOutputStream(AudioManagerBase* manager, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 | 143 |
| 146 namespace media { | 144 namespace media { |
| 147 | 145 |
| 148 class AudioOutputProxyTest : public testing::Test { | 146 class AudioOutputProxyTest : public testing::Test { |
| 149 protected: | 147 protected: |
| 150 virtual void SetUp() { | 148 virtual void SetUp() { |
| 151 EXPECT_CALL(manager_, GetMessageLoop()) | 149 EXPECT_CALL(manager_, GetMessageLoop()) |
| 152 .WillRepeatedly(Return(message_loop_.message_loop_proxy())); | 150 .WillRepeatedly(Return(message_loop_.message_loop_proxy())); |
| 153 EXPECT_CALL(manager_, GetWorkerLoop()) | 151 EXPECT_CALL(manager_, GetWorkerLoop()) |
| 154 .WillRepeatedly(Return(message_loop_.message_loop_proxy())); | 152 .WillRepeatedly(Return(message_loop_.message_loop_proxy())); |
| 153 // Use a low sample rate and large buffer size when testing otherwise the |
| 154 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e., |
| 155 // RunUntilIdle() will never terminate. |
| 156 params_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, |
| 157 CHANNEL_LAYOUT_STEREO, 8000, 16, 2048); |
| 155 InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs)); | 158 InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs)); |
| 156 } | 159 } |
| 157 | 160 |
| 158 virtual void TearDown() { | 161 virtual void TearDown() { |
| 159 // All paused proxies should have been closed at this point. | |
| 160 EXPECT_EQ(0u, dispatcher_impl_->paused_proxies_); | |
| 161 | |
| 162 // This is necessary to free all proxy objects that have been | 162 // This is necessary to free all proxy objects that have been |
| 163 // closed by the test. | 163 // closed by the test. |
| 164 message_loop_.RunUntilIdle(); | 164 message_loop_.RunUntilIdle(); |
| 165 } | 165 } |
| 166 | 166 |
| 167 virtual void InitDispatcher(base::TimeDelta close_delay) { | 167 virtual void InitDispatcher(base::TimeDelta close_delay) { |
| 168 // Use a low sample rate and large buffer size when testing otherwise the | |
| 169 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e., | |
| 170 // RunUntilIdle() will never terminate. | |
| 171 params_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, | |
| 172 CHANNEL_LAYOUT_STEREO, 8000, 16, 2048); | |
| 173 dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(), | 168 dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(), |
| 174 params_, | 169 params_, |
| 175 std::string(), | 170 std::string(), |
| 176 std::string(), | 171 std::string(), |
| 177 close_delay); | 172 close_delay); |
| 178 | |
| 179 // Necessary to know how long the dispatcher will wait before posting | |
| 180 // StopStreamTask. | |
| 181 pause_delay_ = dispatcher_impl_->pause_delay_; | |
| 182 } | 173 } |
| 183 | 174 |
| 184 virtual void OnStart() {} | 175 virtual void OnStart() {} |
| 185 | 176 |
| 186 MockAudioManager& manager() { | 177 MockAudioManager& manager() { |
| 187 return manager_; | 178 return manager_; |
| 188 } | 179 } |
| 189 | 180 |
| 190 // Wait for the close timer to fire. | 181 void WaitForCloseTimer(MockAudioOutputStream* stream) { |
| 191 void WaitForCloseTimer(const int timer_delay_ms) { | 182 base::RunLoop run_loop; |
| 192 message_loop_.RunUntilIdle(); // OpenTask() may reset the timer. | 183 EXPECT_CALL(*stream, Close()) |
| 193 base::PlatformThread::Sleep( | 184 .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); |
| 194 base::TimeDelta::FromMilliseconds(timer_delay_ms) * 2); | 185 run_loop.Run(); |
| 195 message_loop_.RunUntilIdle(); | |
| 196 } | 186 } |
| 197 | 187 |
| 198 // Methods that do actual tests. | 188 void CloseAndWaitForCloseTimer(AudioOutputProxy* proxy, |
| 189 MockAudioOutputStream* stream) { |
| 190 // Close the stream and verify it doesn't happen immediately. |
| 191 proxy->Close(); |
| 192 Mock::VerifyAndClear(stream); |
| 193 |
| 194 // Wait for the actual close event to come from the close timer. |
| 195 WaitForCloseTimer(stream); |
| 196 } |
| 197 |
| 198 // Basic Open() and Close() test. |
| 199 void OpenAndClose(AudioOutputDispatcher* dispatcher) { | 199 void OpenAndClose(AudioOutputDispatcher* dispatcher) { |
| 200 MockAudioOutputStream stream(&manager_, params_); | 200 MockAudioOutputStream stream(&manager_, params_); |
| 201 | 201 |
| 202 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 202 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 203 .WillOnce(Return(&stream)); | 203 .WillOnce(Return(&stream)); |
| 204 EXPECT_CALL(stream, Open()) | 204 EXPECT_CALL(stream, Open()) |
| 205 .WillOnce(Return(true)); | 205 .WillOnce(Return(true)); |
| 206 EXPECT_CALL(stream, Close()) | |
| 207 .Times(1); | |
| 208 | 206 |
| 209 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); | 207 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); |
| 210 EXPECT_TRUE(proxy->Open()); | 208 EXPECT_TRUE(proxy->Open()); |
| 211 proxy->Close(); | 209 CloseAndWaitForCloseTimer(proxy, &stream); |
| 212 WaitForCloseTimer(kTestCloseDelayMs); | |
| 213 } | 210 } |
| 214 | 211 |
| 215 // Create a stream, and then calls Start() and Stop(). | 212 // Creates a stream, and then calls Start() and Stop(). |
| 216 void StartAndStop(AudioOutputDispatcher* dispatcher) { | 213 void StartAndStop(AudioOutputDispatcher* dispatcher) { |
| 217 MockAudioOutputStream stream(&manager_, params_); | 214 MockAudioOutputStream stream(&manager_, params_); |
| 218 | 215 |
| 219 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 216 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 220 .WillOnce(Return(&stream)); | 217 .WillOnce(Return(&stream)); |
| 221 EXPECT_CALL(stream, Open()) | 218 EXPECT_CALL(stream, Open()) |
| 222 .WillOnce(Return(true)); | 219 .WillOnce(Return(true)); |
| 223 EXPECT_CALL(stream, SetVolume(_)) | 220 EXPECT_CALL(stream, SetVolume(_)) |
| 224 .Times(1); | 221 .Times(1); |
| 225 EXPECT_CALL(stream, Close()) | |
| 226 .Times(1); | |
| 227 | 222 |
| 228 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); | 223 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); |
| 229 EXPECT_TRUE(proxy->Open()); | 224 EXPECT_TRUE(proxy->Open()); |
| 230 | 225 |
| 231 proxy->Start(&callback_); | 226 proxy->Start(&callback_); |
| 232 OnStart(); | 227 OnStart(); |
| 233 proxy->Stop(); | 228 proxy->Stop(); |
| 234 | 229 |
| 235 proxy->Close(); | 230 CloseAndWaitForCloseTimer(proxy, &stream); |
| 236 WaitForCloseTimer(kTestCloseDelayMs); | |
| 237 EXPECT_TRUE(stream.stop_called()); | 231 EXPECT_TRUE(stream.stop_called()); |
| 238 EXPECT_TRUE(stream.start_called()); | 232 EXPECT_TRUE(stream.start_called()); |
| 239 } | 233 } |
| 240 | 234 |
| 241 // Verify that the stream is closed after Stop is called. | 235 // Verify that the stream is closed after Stop() is called. |
| 242 void CloseAfterStop(AudioOutputDispatcher* dispatcher) { | 236 void CloseAfterStop(AudioOutputDispatcher* dispatcher) { |
| 243 MockAudioOutputStream stream(&manager_, params_); | 237 MockAudioOutputStream stream(&manager_, params_); |
| 244 | 238 |
| 245 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 239 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 246 .WillOnce(Return(&stream)); | 240 .WillOnce(Return(&stream)); |
| 247 EXPECT_CALL(stream, Open()) | 241 EXPECT_CALL(stream, Open()) |
| 248 .WillOnce(Return(true)); | 242 .WillOnce(Return(true)); |
| 249 EXPECT_CALL(stream, SetVolume(_)) | 243 EXPECT_CALL(stream, SetVolume(_)) |
| 250 .Times(1); | 244 .Times(1); |
| 251 EXPECT_CALL(stream, Close()) | |
| 252 .Times(1); | |
| 253 | 245 |
| 254 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); | 246 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); |
| 255 EXPECT_TRUE(proxy->Open()); | 247 EXPECT_TRUE(proxy->Open()); |
| 256 | 248 |
| 257 proxy->Start(&callback_); | 249 proxy->Start(&callback_); |
| 258 OnStart(); | 250 OnStart(); |
| 259 proxy->Stop(); | 251 proxy->Stop(); |
| 260 | 252 |
| 261 // Wait for StopStream() to post StopStreamTask(). | 253 // Wait for the close timer to fire after StopStream(). |
| 262 base::PlatformThread::Sleep(pause_delay_ * 2); | 254 WaitForCloseTimer(&stream); |
| 263 WaitForCloseTimer(kTestCloseDelayMs); | |
| 264 | |
| 265 // Verify expectation before calling Close(). | |
| 266 Mock::VerifyAndClear(&stream); | |
| 267 | |
| 268 proxy->Close(); | 255 proxy->Close(); |
| 269 EXPECT_TRUE(stream.stop_called()); | 256 EXPECT_TRUE(stream.stop_called()); |
| 270 EXPECT_TRUE(stream.start_called()); | 257 EXPECT_TRUE(stream.start_called()); |
| 271 } | 258 } |
| 272 | 259 |
| 273 // Create two streams, but don't start them. Only one device must be open. | 260 // Create two streams, but don't start them. Only one device must be opened. |
| 274 void TwoStreams(AudioOutputDispatcher* dispatcher) { | 261 void TwoStreams(AudioOutputDispatcher* dispatcher) { |
| 275 MockAudioOutputStream stream(&manager_, params_); | 262 MockAudioOutputStream stream(&manager_, params_); |
| 276 | 263 |
| 277 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 264 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 278 .WillOnce(Return(&stream)); | 265 .WillOnce(Return(&stream)); |
| 279 EXPECT_CALL(stream, Open()) | 266 EXPECT_CALL(stream, Open()) |
| 280 .WillOnce(Return(true)); | 267 .WillOnce(Return(true)); |
| 281 EXPECT_CALL(stream, Close()) | |
| 282 .Times(1); | |
| 283 | 268 |
| 284 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); | 269 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); |
| 285 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); | 270 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); |
| 286 EXPECT_TRUE(proxy1->Open()); | 271 EXPECT_TRUE(proxy1->Open()); |
| 287 EXPECT_TRUE(proxy2->Open()); | 272 EXPECT_TRUE(proxy2->Open()); |
| 288 proxy1->Close(); | 273 proxy1->Close(); |
| 289 proxy2->Close(); | 274 CloseAndWaitForCloseTimer(proxy2, &stream); |
| 290 WaitForCloseTimer(kTestCloseDelayMs); | |
| 291 EXPECT_FALSE(stream.stop_called()); | 275 EXPECT_FALSE(stream.stop_called()); |
| 292 EXPECT_FALSE(stream.start_called()); | 276 EXPECT_FALSE(stream.start_called()); |
| 293 } | 277 } |
| 294 | 278 |
| 295 // Open() method failed. | 279 // Open() method failed. |
| 296 void OpenFailed(AudioOutputDispatcher* dispatcher) { | 280 void OpenFailed(AudioOutputDispatcher* dispatcher) { |
| 297 MockAudioOutputStream stream(&manager_, params_); | 281 MockAudioOutputStream stream(&manager_, params_); |
| 298 | 282 |
| 299 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 283 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 300 .WillOnce(Return(&stream)); | 284 .WillOnce(Return(&stream)); |
| 301 EXPECT_CALL(stream, Open()) | 285 EXPECT_CALL(stream, Open()) |
| 302 .WillOnce(Return(false)); | 286 .WillOnce(Return(false)); |
| 303 EXPECT_CALL(stream, Close()) | 287 EXPECT_CALL(stream, Close()) |
| 304 .Times(1); | 288 .Times(1); |
| 305 | 289 |
| 306 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); | 290 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); |
| 307 EXPECT_FALSE(proxy->Open()); | 291 EXPECT_FALSE(proxy->Open()); |
| 308 proxy->Close(); | 292 proxy->Close(); |
| 309 WaitForCloseTimer(kTestCloseDelayMs); | |
| 310 EXPECT_FALSE(stream.stop_called()); | 293 EXPECT_FALSE(stream.stop_called()); |
| 311 EXPECT_FALSE(stream.start_called()); | 294 EXPECT_FALSE(stream.start_called()); |
| 312 } | 295 } |
| 313 | 296 |
| 314 void CreateAndWait(AudioOutputDispatcher* dispatcher) { | 297 void CreateAndWait(AudioOutputDispatcher* dispatcher) { |
| 315 MockAudioOutputStream stream(&manager_, params_); | 298 MockAudioOutputStream stream(&manager_, params_); |
| 316 | 299 |
| 317 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 300 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 318 .WillOnce(Return(&stream)); | 301 .WillOnce(Return(&stream)); |
| 319 EXPECT_CALL(stream, Open()) | 302 EXPECT_CALL(stream, Open()) |
| 320 .WillOnce(Return(true)); | 303 .WillOnce(Return(true)); |
| 321 EXPECT_CALL(stream, Close()) | |
| 322 .Times(1); | |
| 323 | 304 |
| 324 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); | 305 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); |
| 325 EXPECT_TRUE(proxy->Open()); | 306 EXPECT_TRUE(proxy->Open()); |
| 326 | 307 |
| 327 // Simulate a delay. | 308 WaitForCloseTimer(&stream); |
| 328 base::PlatformThread::Sleep( | |
| 329 base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2); | |
| 330 message_loop_.RunUntilIdle(); | |
| 331 | |
| 332 // Verify expectation before calling Close(). | |
| 333 Mock::VerifyAndClear(&stream); | |
| 334 | |
| 335 proxy->Close(); | 309 proxy->Close(); |
| 336 EXPECT_FALSE(stream.stop_called()); | 310 EXPECT_FALSE(stream.stop_called()); |
| 337 EXPECT_FALSE(stream.start_called()); | 311 EXPECT_FALSE(stream.start_called()); |
| 338 } | 312 } |
| 339 | 313 |
| 340 void TwoStreams_OnePlaying(AudioOutputDispatcher* dispatcher) { | 314 void OneStream_TwoPlays(AudioOutputDispatcher* dispatcher) { |
| 341 MockAudioOutputStream stream1(&manager_, params_); | 315 MockAudioOutputStream stream(&manager_, params_); |
| 342 MockAudioOutputStream stream2(&manager_, params_); | |
| 343 | 316 |
| 344 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 317 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 345 .WillOnce(Return(&stream1)) | 318 .WillOnce(Return(&stream)); |
| 346 .WillOnce(Return(&stream2)); | |
| 347 | 319 |
| 348 EXPECT_CALL(stream1, Open()) | 320 EXPECT_CALL(stream, Open()) |
| 349 .WillOnce(Return(true)); | 321 .WillOnce(Return(true)); |
| 350 EXPECT_CALL(stream1, SetVolume(_)) | 322 EXPECT_CALL(stream, SetVolume(_)) |
| 351 .Times(1); | 323 .Times(2); |
| 352 EXPECT_CALL(stream1, Close()) | |
| 353 .Times(1); | |
| 354 | |
| 355 EXPECT_CALL(stream2, Open()) | |
| 356 .WillOnce(Return(true)); | |
| 357 EXPECT_CALL(stream2, Close()) | |
| 358 .Times(1); | |
| 359 | 324 |
| 360 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); | 325 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); |
| 361 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); | |
| 362 EXPECT_TRUE(proxy1->Open()); | 326 EXPECT_TRUE(proxy1->Open()); |
| 363 | 327 |
| 364 proxy1->Start(&callback_); | 328 proxy1->Start(&callback_); |
| 365 EXPECT_TRUE(proxy2->Open()); | |
| 366 message_loop_.RunUntilIdle(); | |
| 367 OnStart(); | 329 OnStart(); |
| 368 proxy1->Stop(); | 330 proxy1->Stop(); |
| 369 | 331 |
| 332 // The stream should now be idle and get reused by |proxy2|. |
| 333 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); |
| 334 EXPECT_TRUE(proxy2->Open()); |
| 335 proxy2->Start(&callback_); |
| 336 OnStart(); |
| 337 proxy2->Stop(); |
| 338 |
| 370 proxy1->Close(); | 339 proxy1->Close(); |
| 371 proxy2->Close(); | 340 CloseAndWaitForCloseTimer(proxy2, &stream); |
| 372 EXPECT_TRUE(stream1.stop_called()); | 341 EXPECT_TRUE(stream.stop_called()); |
| 373 EXPECT_TRUE(stream1.start_called()); | 342 EXPECT_TRUE(stream.start_called()); |
| 374 EXPECT_FALSE(stream2.stop_called()); | |
| 375 EXPECT_FALSE(stream2.start_called()); | |
| 376 } | 343 } |
| 377 | 344 |
| 378 void TwoStreams_BothPlaying(AudioOutputDispatcher* dispatcher) { | 345 void TwoStreams_BothPlaying(AudioOutputDispatcher* dispatcher) { |
| 379 MockAudioOutputStream stream1(&manager_, params_); | 346 MockAudioOutputStream stream1(&manager_, params_); |
| 380 MockAudioOutputStream stream2(&manager_, params_); | 347 MockAudioOutputStream stream2(&manager_, params_); |
| 381 | 348 |
| 382 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 349 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 383 .WillOnce(Return(&stream1)) | 350 .WillOnce(Return(&stream1)) |
| 384 .WillOnce(Return(&stream2)); | 351 .WillOnce(Return(&stream2)); |
| 385 | 352 |
| 386 EXPECT_CALL(stream1, Open()) | 353 EXPECT_CALL(stream1, Open()) |
| 387 .WillOnce(Return(true)); | 354 .WillOnce(Return(true)); |
| 388 EXPECT_CALL(stream1, SetVolume(_)) | 355 EXPECT_CALL(stream1, SetVolume(_)) |
| 389 .Times(1); | 356 .Times(1); |
| 390 EXPECT_CALL(stream1, Close()) | |
| 391 .Times(1); | |
| 392 | 357 |
| 393 EXPECT_CALL(stream2, Open()) | 358 EXPECT_CALL(stream2, Open()) |
| 394 .WillOnce(Return(true)); | 359 .WillOnce(Return(true)); |
| 395 EXPECT_CALL(stream2, SetVolume(_)) | 360 EXPECT_CALL(stream2, SetVolume(_)) |
| 396 .Times(1); | 361 .Times(1); |
| 397 EXPECT_CALL(stream2, Close()) | |
| 398 .Times(1); | |
| 399 | 362 |
| 400 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); | 363 AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher); |
| 401 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); | 364 AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher); |
| 402 EXPECT_TRUE(proxy1->Open()); | 365 EXPECT_TRUE(proxy1->Open()); |
| 403 EXPECT_TRUE(proxy2->Open()); | 366 EXPECT_TRUE(proxy2->Open()); |
| 404 | 367 |
| 405 proxy1->Start(&callback_); | 368 proxy1->Start(&callback_); |
| 406 proxy2->Start(&callback_); | 369 proxy2->Start(&callback_); |
| 407 OnStart(); | 370 OnStart(); |
| 408 proxy1->Stop(); | 371 proxy1->Stop(); |
| 372 CloseAndWaitForCloseTimer(proxy1, &stream1); |
| 373 |
| 409 proxy2->Stop(); | 374 proxy2->Stop(); |
| 375 CloseAndWaitForCloseTimer(proxy2, &stream2); |
| 410 | 376 |
| 411 proxy1->Close(); | |
| 412 proxy2->Close(); | |
| 413 EXPECT_TRUE(stream1.stop_called()); | 377 EXPECT_TRUE(stream1.stop_called()); |
| 414 EXPECT_TRUE(stream1.start_called()); | 378 EXPECT_TRUE(stream1.start_called()); |
| 415 EXPECT_TRUE(stream2.stop_called()); | 379 EXPECT_TRUE(stream2.stop_called()); |
| 416 EXPECT_TRUE(stream2.start_called()); | 380 EXPECT_TRUE(stream2.start_called()); |
| 417 } | 381 } |
| 418 | 382 |
| 419 void StartFailed(AudioOutputDispatcher* dispatcher) { | 383 void StartFailed(AudioOutputDispatcher* dispatcher) { |
| 420 MockAudioOutputStream stream(&manager_, params_); | 384 MockAudioOutputStream stream(&manager_, params_); |
| 421 | 385 |
| 422 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 386 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 423 .WillOnce(Return(&stream)); | 387 .WillOnce(Return(&stream)); |
| 424 EXPECT_CALL(stream, Open()) | 388 EXPECT_CALL(stream, Open()) |
| 425 .WillOnce(Return(true)); | 389 .WillOnce(Return(true)); |
| 426 EXPECT_CALL(stream, Close()) | |
| 427 .Times(1); | |
| 428 | 390 |
| 429 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); | 391 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher); |
| 430 EXPECT_TRUE(proxy->Open()); | 392 EXPECT_TRUE(proxy->Open()); |
| 431 | 393 |
| 432 // Simulate a delay. | 394 WaitForCloseTimer(&stream); |
| 433 base::PlatformThread::Sleep( | |
| 434 base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2); | |
| 435 message_loop_.RunUntilIdle(); | |
| 436 | |
| 437 // Verify expectation before calling Close(). | |
| 438 Mock::VerifyAndClear(&stream); | |
| 439 | 395 |
| 440 // |stream| is closed at this point. Start() should reopen it again. | 396 // |stream| is closed at this point. Start() should reopen it again. |
| 441 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 397 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 442 .Times(2) | 398 .Times(2) |
| 443 .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream*>(NULL))); | 399 .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream*>(NULL))); |
| 444 | 400 |
| 445 EXPECT_CALL(callback_, OnError(_)) | 401 EXPECT_CALL(callback_, OnError(_)) |
| 446 .Times(2); | 402 .Times(2); |
| 447 | 403 |
| 448 proxy->Start(&callback_); | 404 proxy->Start(&callback_); |
| 449 | 405 |
| 450 // Double Start() in the error case should be allowed since it's possible a | 406 // Double Start() in the error case should be allowed since it's possible a |
| 451 // callback may not have had time to process the OnError() in between. | 407 // callback may not have had time to process the OnError() in between. |
| 452 proxy->Stop(); | 408 proxy->Stop(); |
| 453 proxy->Start(&callback_); | 409 proxy->Start(&callback_); |
| 454 | 410 |
| 455 Mock::VerifyAndClear(&callback_); | 411 Mock::VerifyAndClear(&callback_); |
| 456 | 412 |
| 457 proxy->Close(); | 413 proxy->Close(); |
| 458 } | 414 } |
| 459 | 415 |
| 460 base::MessageLoop message_loop_; | 416 base::MessageLoop message_loop_; |
| 461 scoped_refptr<AudioOutputDispatcherImpl> dispatcher_impl_; | 417 scoped_refptr<AudioOutputDispatcherImpl> dispatcher_impl_; |
| 462 base::TimeDelta pause_delay_; | |
| 463 MockAudioManager manager_; | 418 MockAudioManager manager_; |
| 464 MockAudioSourceCallback callback_; | 419 MockAudioSourceCallback callback_; |
| 465 AudioParameters params_; | 420 AudioParameters params_; |
| 466 }; | 421 }; |
| 467 | 422 |
| 468 class AudioOutputResamplerTest : public AudioOutputProxyTest { | 423 class AudioOutputResamplerTest : public AudioOutputProxyTest { |
| 469 public: | 424 public: |
| 470 virtual void TearDown() { | 425 virtual void TearDown() { |
| 471 AudioOutputProxyTest::TearDown(); | 426 AudioOutputProxyTest::TearDown(); |
| 472 } | 427 } |
| 473 | 428 |
| 474 virtual void InitDispatcher(base::TimeDelta close_delay) OVERRIDE { | 429 virtual void InitDispatcher(base::TimeDelta close_delay) OVERRIDE { |
| 475 AudioOutputProxyTest::InitDispatcher(close_delay); | |
| 476 // Use a low sample rate and large buffer size when testing otherwise the | 430 // Use a low sample rate and large buffer size when testing otherwise the |
| 477 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e., | 431 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e., |
| 478 // RunUntilIdle() will never terminate. | 432 // RunUntilIdle() will never terminate. |
| 479 resampler_params_ = AudioParameters( | 433 resampler_params_ = AudioParameters( |
| 480 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, | 434 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, |
| 481 16000, 16, 1024); | 435 16000, 16, 1024); |
| 482 resampler_ = new AudioOutputResampler( | 436 resampler_ = new AudioOutputResampler( |
| 483 &manager(), params_, resampler_params_, std::string(), std::string(), | 437 &manager(), params_, resampler_params_, std::string(), std::string(), |
| 484 close_delay); | 438 close_delay); |
| 485 } | 439 } |
| 486 | 440 |
| 487 virtual void OnStart() OVERRIDE { | 441 virtual void OnStart() OVERRIDE { |
| 488 // Let start run for a bit. | 442 // Let Start() run for a bit. |
| 489 message_loop_.RunUntilIdle(); | 443 base::RunLoop run_loop; |
| 490 base::PlatformThread::Sleep( | 444 message_loop_.PostDelayedTask( |
| 445 FROM_HERE, |
| 446 run_loop.QuitClosure(), |
| 491 base::TimeDelta::FromMilliseconds(kStartRunTimeMs)); | 447 base::TimeDelta::FromMilliseconds(kStartRunTimeMs)); |
| 448 run_loop.Run(); |
| 492 } | 449 } |
| 493 | 450 |
| 494 protected: | 451 protected: |
| 495 AudioParameters resampler_params_; | 452 AudioParameters resampler_params_; |
| 496 scoped_refptr<AudioOutputResampler> resampler_; | 453 scoped_refptr<AudioOutputResampler> resampler_; |
| 497 }; | 454 }; |
| 498 | 455 |
| 499 TEST_F(AudioOutputProxyTest, CreateAndClose) { | 456 TEST_F(AudioOutputProxyTest, CreateAndClose) { |
| 500 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_.get()); | 457 AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_); |
| 501 proxy->Close(); | 458 proxy->Close(); |
| 502 } | 459 } |
| 503 | 460 |
| 504 TEST_F(AudioOutputResamplerTest, CreateAndClose) { | 461 TEST_F(AudioOutputResamplerTest, CreateAndClose) { |
| 505 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get()); | 462 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); |
| 506 proxy->Close(); | 463 proxy->Close(); |
| 507 } | 464 } |
| 508 | 465 |
| 509 TEST_F(AudioOutputProxyTest, OpenAndClose) { | 466 TEST_F(AudioOutputProxyTest, OpenAndClose) { |
| 510 OpenAndClose(dispatcher_impl_.get()); | 467 OpenAndClose(dispatcher_impl_); |
| 511 } | 468 } |
| 512 | 469 |
| 513 TEST_F(AudioOutputResamplerTest, OpenAndClose) { | 470 TEST_F(AudioOutputResamplerTest, OpenAndClose) { |
| 514 OpenAndClose(resampler_.get()); | 471 OpenAndClose(resampler_); |
| 515 } | 472 } |
| 516 | 473 |
| 517 // Create a stream, and verify that it is closed after kTestCloseDelayMs. | 474 // Create a stream, and verify that it is closed after kTestCloseDelayMs. |
| 518 // if it doesn't start playing. | 475 // if it doesn't start playing. |
| 519 TEST_F(AudioOutputProxyTest, CreateAndWait) { | 476 TEST_F(AudioOutputProxyTest, CreateAndWait) { |
| 520 CreateAndWait(dispatcher_impl_.get()); | 477 CreateAndWait(dispatcher_impl_); |
| 521 } | 478 } |
| 522 | 479 |
| 523 // Create a stream, and verify that it is closed after kTestCloseDelayMs. | 480 // Create a stream, and verify that it is closed after kTestCloseDelayMs. |
| 524 // if it doesn't start playing. | 481 // if it doesn't start playing. |
| 525 TEST_F(AudioOutputResamplerTest, CreateAndWait) { | 482 TEST_F(AudioOutputResamplerTest, CreateAndWait) { |
| 526 CreateAndWait(resampler_.get()); | 483 CreateAndWait(resampler_); |
| 527 } | 484 } |
| 528 | 485 |
| 529 TEST_F(AudioOutputProxyTest, StartAndStop) { | 486 TEST_F(AudioOutputProxyTest, StartAndStop) { |
| 530 StartAndStop(dispatcher_impl_.get()); | 487 StartAndStop(dispatcher_impl_); |
| 531 } | 488 } |
| 532 | 489 |
| 533 TEST_F(AudioOutputResamplerTest, StartAndStop) { | 490 TEST_F(AudioOutputResamplerTest, StartAndStop) { |
| 534 StartAndStop(resampler_.get()); | 491 StartAndStop(resampler_); |
| 535 } | 492 } |
| 536 | 493 |
| 537 TEST_F(AudioOutputProxyTest, CloseAfterStop) { | 494 TEST_F(AudioOutputProxyTest, CloseAfterStop) { |
| 538 CloseAfterStop(dispatcher_impl_.get()); | 495 CloseAfterStop(dispatcher_impl_); |
| 539 } | 496 } |
| 540 | 497 |
| 541 TEST_F(AudioOutputResamplerTest, CloseAfterStop) { | 498 TEST_F(AudioOutputResamplerTest, CloseAfterStop) { |
| 542 CloseAfterStop(resampler_.get()); | 499 CloseAfterStop(resampler_); |
| 543 } | 500 } |
| 544 | 501 |
| 545 TEST_F(AudioOutputProxyTest, TwoStreams) { TwoStreams(dispatcher_impl_.get()); } | 502 TEST_F(AudioOutputProxyTest, TwoStreams) { TwoStreams(dispatcher_impl_); } |
| 546 | 503 |
| 547 TEST_F(AudioOutputResamplerTest, TwoStreams) { TwoStreams(resampler_.get()); } | 504 TEST_F(AudioOutputResamplerTest, TwoStreams) { TwoStreams(resampler_); } |
| 548 | 505 |
| 549 // Two streams: verify that second stream is allocated when the first | 506 // Two streams: verify that second stream is allocated when the first |
| 550 // starts playing. | 507 // starts playing. |
| 551 TEST_F(AudioOutputProxyTest, TwoStreams_OnePlaying) { | 508 TEST_F(AudioOutputProxyTest, OneStream_TwoPlays) { |
| 552 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); | 509 OneStream_TwoPlays(dispatcher_impl_); |
| 553 TwoStreams_OnePlaying(dispatcher_impl_.get()); | |
| 554 } | 510 } |
| 555 | 511 |
| 556 TEST_F(AudioOutputResamplerTest, TwoStreams_OnePlaying) { | 512 TEST_F(AudioOutputResamplerTest, OneStream_TwoPlays) { |
| 557 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); | 513 OneStream_TwoPlays(resampler_); |
| 558 TwoStreams_OnePlaying(resampler_.get()); | |
| 559 } | 514 } |
| 560 | 515 |
| 561 // Two streams, both are playing. Dispatcher should not open a third stream. | 516 // Two streams, both are playing. Dispatcher should not open a third stream. |
| 562 TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) { | 517 TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) { |
| 563 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); | 518 TwoStreams_BothPlaying(dispatcher_impl_); |
| 564 TwoStreams_BothPlaying(dispatcher_impl_.get()); | |
| 565 } | 519 } |
| 566 | 520 |
| 567 TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) { | 521 TEST_F(AudioOutputResamplerTest, TwoStreams_BothPlaying) { |
| 568 InitDispatcher(base::TimeDelta::FromSeconds(kTestBigCloseDelaySeconds)); | 522 TwoStreams_BothPlaying(resampler_); |
| 569 TwoStreams_BothPlaying(resampler_.get()); | |
| 570 } | 523 } |
| 571 | 524 |
| 572 TEST_F(AudioOutputProxyTest, OpenFailed) { OpenFailed(dispatcher_impl_.get()); } | 525 TEST_F(AudioOutputProxyTest, OpenFailed) { OpenFailed(dispatcher_impl_); } |
| 573 | 526 |
| 574 // Start() method failed. | 527 // Start() method failed. |
| 575 TEST_F(AudioOutputProxyTest, StartFailed) { | 528 TEST_F(AudioOutputProxyTest, StartFailed) { |
| 576 StartFailed(dispatcher_impl_.get()); | 529 StartFailed(dispatcher_impl_); |
| 577 } | 530 } |
| 578 | 531 |
| 579 TEST_F(AudioOutputResamplerTest, StartFailed) { StartFailed(resampler_.get()); } | 532 TEST_F(AudioOutputResamplerTest, StartFailed) { StartFailed(resampler_); } |
| 580 | 533 |
| 581 // Simulate AudioOutputStream::Create() failure with a low latency stream and | 534 // Simulate AudioOutputStream::Create() failure with a low latency stream and |
| 582 // ensure AudioOutputResampler falls back to the high latency path. | 535 // ensure AudioOutputResampler falls back to the high latency path. |
| 583 TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) { | 536 TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) { |
| 584 MockAudioOutputStream stream(&manager_, params_); | 537 MockAudioOutputStream stream(&manager_, params_); |
| 585 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 538 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 586 .Times(2) | 539 .Times(2) |
| 587 .WillOnce(Return(static_cast<AudioOutputStream*>(NULL))) | 540 .WillOnce(Return(static_cast<AudioOutputStream*>(NULL))) |
| 588 .WillRepeatedly(Return(&stream)); | 541 .WillRepeatedly(Return(&stream)); |
| 589 EXPECT_CALL(stream, Open()) | 542 EXPECT_CALL(stream, Open()) |
| 590 .WillOnce(Return(true)); | 543 .WillOnce(Return(true)); |
| 591 EXPECT_CALL(stream, Close()) | |
| 592 .Times(1); | |
| 593 | 544 |
| 594 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get()); | 545 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); |
| 595 EXPECT_TRUE(proxy->Open()); | 546 EXPECT_TRUE(proxy->Open()); |
| 596 proxy->Close(); | 547 CloseAndWaitForCloseTimer(proxy, &stream); |
| 597 WaitForCloseTimer(kTestCloseDelayMs); | |
| 598 } | 548 } |
| 599 | 549 |
| 600 // Simulate AudioOutputStream::Open() failure with a low latency stream and | 550 // Simulate AudioOutputStream::Open() failure with a low latency stream and |
| 601 // ensure AudioOutputResampler falls back to the high latency path. | 551 // ensure AudioOutputResampler falls back to the high latency path. |
| 602 TEST_F(AudioOutputResamplerTest, LowLatencyOpenFailedFallback) { | 552 TEST_F(AudioOutputResamplerTest, LowLatencyOpenFailedFallback) { |
| 603 MockAudioOutputStream failed_stream(&manager_, params_); | 553 MockAudioOutputStream failed_stream(&manager_, params_); |
| 604 MockAudioOutputStream okay_stream(&manager_, params_); | 554 MockAudioOutputStream okay_stream(&manager_, params_); |
| 605 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 555 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 606 .Times(2) | 556 .Times(2) |
| 607 .WillOnce(Return(&failed_stream)) | 557 .WillOnce(Return(&failed_stream)) |
| 608 .WillRepeatedly(Return(&okay_stream)); | 558 .WillRepeatedly(Return(&okay_stream)); |
| 609 EXPECT_CALL(failed_stream, Open()) | 559 EXPECT_CALL(failed_stream, Open()) |
| 610 .WillOnce(Return(false)); | 560 .WillOnce(Return(false)); |
| 611 EXPECT_CALL(failed_stream, Close()) | 561 EXPECT_CALL(failed_stream, Close()) |
| 612 .Times(1); | 562 .Times(1); |
| 613 EXPECT_CALL(okay_stream, Open()) | 563 EXPECT_CALL(okay_stream, Open()) |
| 614 .WillOnce(Return(true)); | 564 .WillOnce(Return(true)); |
| 615 EXPECT_CALL(okay_stream, Close()) | |
| 616 .Times(1); | |
| 617 | 565 |
| 618 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get()); | 566 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); |
| 619 EXPECT_TRUE(proxy->Open()); | 567 EXPECT_TRUE(proxy->Open()); |
| 620 proxy->Close(); | 568 CloseAndWaitForCloseTimer(proxy, &okay_stream); |
| 621 WaitForCloseTimer(kTestCloseDelayMs); | |
| 622 } | 569 } |
| 623 | 570 |
| 624 // Simulate failures to open both the low latency and the fallback high latency | 571 // Simulate failures to open both the low latency and the fallback high latency |
| 625 // stream and ensure AudioOutputResampler falls back to a fake stream. | 572 // stream and ensure AudioOutputResampler falls back to a fake stream. |
| 626 TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) { | 573 TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) { |
| 627 MockAudioOutputStream okay_stream(&manager_, params_); | 574 MockAudioOutputStream okay_stream(&manager_, params_); |
| 628 | 575 |
| 629 // Only Windows has a high latency output driver that is not the same as the low | 576 // Only Windows has a high latency output driver that is not the same as the low |
| 630 // latency path. | 577 // latency path. |
| 631 #if defined(OS_WIN) | 578 #if defined(OS_WIN) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 642 EXPECT_CALL(manager(), MakeAudioOutputStream(AllOf( | 589 EXPECT_CALL(manager(), MakeAudioOutputStream(AllOf( |
| 643 testing::Property(&AudioParameters::format, AudioParameters::AUDIO_FAKE), | 590 testing::Property(&AudioParameters::format, AudioParameters::AUDIO_FAKE), |
| 644 testing::Property(&AudioParameters::sample_rate, params_.sample_rate()), | 591 testing::Property(&AudioParameters::sample_rate, params_.sample_rate()), |
| 645 testing::Property( | 592 testing::Property( |
| 646 &AudioParameters::frames_per_buffer, params_.frames_per_buffer())), | 593 &AudioParameters::frames_per_buffer, params_.frames_per_buffer())), |
| 647 _, _)) | 594 _, _)) |
| 648 .Times(1) | 595 .Times(1) |
| 649 .WillOnce(Return(&okay_stream)); | 596 .WillOnce(Return(&okay_stream)); |
| 650 EXPECT_CALL(okay_stream, Open()) | 597 EXPECT_CALL(okay_stream, Open()) |
| 651 .WillOnce(Return(true)); | 598 .WillOnce(Return(true)); |
| 652 EXPECT_CALL(okay_stream, Close()) | |
| 653 .Times(1); | |
| 654 | 599 |
| 655 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get()); | 600 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); |
| 656 EXPECT_TRUE(proxy->Open()); | 601 EXPECT_TRUE(proxy->Open()); |
| 657 proxy->Close(); | 602 CloseAndWaitForCloseTimer(proxy, &okay_stream); |
| 658 WaitForCloseTimer(kTestCloseDelayMs); | |
| 659 } | 603 } |
| 660 | 604 |
| 661 // Simulate failures to open both the low latency, the fallback high latency | 605 // Simulate failures to open both the low latency, the fallback high latency |
| 662 // stream, and the fake audio output stream and ensure AudioOutputResampler | 606 // stream, and the fake audio output stream and ensure AudioOutputResampler |
| 663 // terminates normally. | 607 // terminates normally. |
| 664 TEST_F(AudioOutputResamplerTest, AllFallbackFailed) { | 608 TEST_F(AudioOutputResamplerTest, AllFallbackFailed) { |
| 665 // Only Windows has a high latency output driver that is not the same as the low | 609 // Only Windows has a high latency output driver that is not the same as the low |
| 666 // latency path. | 610 // latency path. |
| 667 #if defined(OS_WIN) | 611 #if defined(OS_WIN) |
| 668 static const int kFallbackCount = 3; | 612 static const int kFallbackCount = 3; |
| 669 #else | 613 #else |
| 670 static const int kFallbackCount = 2; | 614 static const int kFallbackCount = 2; |
| 671 #endif | 615 #endif |
| 672 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 616 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 673 .Times(kFallbackCount) | 617 .Times(kFallbackCount) |
| 674 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL))); | 618 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL))); |
| 675 | 619 |
| 676 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_.get()); | 620 AudioOutputProxy* proxy = new AudioOutputProxy(resampler_); |
| 677 EXPECT_FALSE(proxy->Open()); | 621 EXPECT_FALSE(proxy->Open()); |
| 678 proxy->Close(); | 622 proxy->Close(); |
| 679 WaitForCloseTimer(kTestCloseDelayMs); | |
| 680 } | 623 } |
| 681 | 624 |
| 682 // Simulate an eventual OpenStream() failure; i.e. successful OpenStream() calls | 625 // Simulate an eventual OpenStream() failure; i.e. successful OpenStream() calls |
| 683 // eventually followed by one which fails; root cause of http://crbug.com/150619 | 626 // eventually followed by one which fails; root cause of http://crbug.com/150619 |
| 684 TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) { | 627 TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) { |
| 685 MockAudioOutputStream stream1(&manager_, params_); | 628 MockAudioOutputStream stream1(&manager_, params_); |
| 686 MockAudioOutputStream stream2(&manager_, params_); | 629 MockAudioOutputStream stream2(&manager_, params_); |
| 687 MockAudioOutputStream stream3(&manager_, params_); | |
| 688 | 630 |
| 689 // Setup the mock such that all three streams are successfully created. | 631 // Setup the mock such that all three streams are successfully created. |
| 690 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 632 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 691 .WillOnce(Return(&stream1)) | 633 .WillOnce(Return(&stream1)) |
| 692 .WillOnce(Return(&stream2)) | 634 .WillOnce(Return(&stream2)) |
| 693 .WillOnce(Return(&stream3)) | |
| 694 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL))); | 635 .WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL))); |
| 695 | 636 |
| 696 // Stream1 should be able to successfully open and start. | 637 // Stream1 should be able to successfully open and start. |
| 697 EXPECT_CALL(stream1, Open()) | 638 EXPECT_CALL(stream1, Open()) |
| 698 .WillOnce(Return(true)); | 639 .WillOnce(Return(true)); |
| 699 EXPECT_CALL(stream1, Close()) | |
| 700 .Times(1); | |
| 701 EXPECT_CALL(stream1, SetVolume(_)) | 640 EXPECT_CALL(stream1, SetVolume(_)) |
| 702 .Times(1); | 641 .Times(1); |
| 703 | 642 |
| 704 // Stream2 should also be able to successfully open and start. | 643 // Stream2 should also be able to successfully open and start. |
| 705 EXPECT_CALL(stream2, Open()) | 644 EXPECT_CALL(stream2, Open()) |
| 706 .WillOnce(Return(true)); | 645 .WillOnce(Return(true)); |
| 707 EXPECT_CALL(stream2, Close()) | |
| 708 .Times(1); | |
| 709 EXPECT_CALL(stream2, SetVolume(_)) | 646 EXPECT_CALL(stream2, SetVolume(_)) |
| 710 .Times(1); | 647 .Times(1); |
| 711 | 648 |
| 712 // Stream3 should fail on Open() (yet still be closed since | |
| 713 // MakeAudioOutputStream returned a valid AudioOutputStream object). | |
| 714 EXPECT_CALL(stream3, Open()) | |
| 715 .WillOnce(Return(false)); | |
| 716 EXPECT_CALL(stream3, Close()) | |
| 717 .Times(1); | |
| 718 | |
| 719 // Open and start the first proxy and stream. | 649 // Open and start the first proxy and stream. |
| 720 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_.get()); | 650 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_); |
| 721 EXPECT_TRUE(proxy1->Open()); | 651 EXPECT_TRUE(proxy1->Open()); |
| 722 proxy1->Start(&callback_); | 652 proxy1->Start(&callback_); |
| 723 OnStart(); | 653 OnStart(); |
| 724 | 654 |
| 725 // Open and start the second proxy and stream. | 655 // Open and start the second proxy and stream. |
| 726 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get()); | 656 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_); |
| 727 EXPECT_TRUE(proxy2->Open()); | 657 EXPECT_TRUE(proxy2->Open()); |
| 728 proxy2->Start(&callback_); | 658 proxy2->Start(&callback_); |
| 729 OnStart(); | 659 OnStart(); |
| 730 | 660 |
| 731 // Attempt to open the third stream which should fail. | 661 // Attempt to open the third stream which should fail. |
| 732 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get()); | 662 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_); |
| 733 EXPECT_FALSE(proxy3->Open()); | 663 EXPECT_FALSE(proxy3->Open()); |
| 664 proxy3->Close(); |
| 734 | 665 |
| 735 // Perform the required Stop()/Close() shutdown dance for each proxy. Under | 666 // Perform the required Stop()/Close() shutdown dance for each proxy. Under |
| 736 // the hood each proxy should correctly call CloseStream() if OpenStream() | 667 // the hood each proxy should correctly call CloseStream() if OpenStream() |
| 737 // succeeded or not. | 668 // succeeded or not. |
| 738 proxy3->Stop(); | |
| 739 proxy3->Close(); | |
| 740 proxy2->Stop(); | 669 proxy2->Stop(); |
| 741 proxy2->Close(); | 670 CloseAndWaitForCloseTimer(proxy2, &stream2); |
| 671 |
| 742 proxy1->Stop(); | 672 proxy1->Stop(); |
| 743 proxy1->Close(); | 673 CloseAndWaitForCloseTimer(proxy1, &stream1); |
| 744 | 674 |
| 745 // Wait for all of the messages to fly and then verify stream behavior. | |
| 746 WaitForCloseTimer(kTestCloseDelayMs); | |
| 747 EXPECT_TRUE(stream1.stop_called()); | 675 EXPECT_TRUE(stream1.stop_called()); |
| 748 EXPECT_TRUE(stream1.start_called()); | 676 EXPECT_TRUE(stream1.start_called()); |
| 749 EXPECT_TRUE(stream2.stop_called()); | 677 EXPECT_TRUE(stream2.stop_called()); |
| 750 EXPECT_TRUE(stream2.start_called()); | 678 EXPECT_TRUE(stream2.start_called()); |
| 751 EXPECT_FALSE(stream3.stop_called()); | |
| 752 EXPECT_FALSE(stream3.start_called()); | |
| 753 } | 679 } |
| 754 | 680 |
| 755 // Ensures the methods used to fix audio output wedges are working correctly. | 681 // Ensures the methods used to fix audio output wedges are working correctly. |
| 756 TEST_F(AudioOutputResamplerTest, WedgeFix) { | 682 TEST_F(AudioOutputResamplerTest, WedgeFix) { |
| 757 MockAudioOutputStream stream1(&manager_, params_); | 683 MockAudioOutputStream stream1(&manager_, params_); |
| 758 MockAudioOutputStream stream2(&manager_, params_); | 684 MockAudioOutputStream stream2(&manager_, params_); |
| 759 MockAudioOutputStream stream3(&manager_, params_); | 685 MockAudioOutputStream stream3(&manager_, params_); |
| 760 | 686 |
| 761 // Setup the mock such that all three streams are successfully created. | 687 // Setup the mock such that all three streams are successfully created. |
| 762 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) | 688 EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _)) |
| 763 .WillOnce(Return(&stream1)) | 689 .WillOnce(Return(&stream1)) |
| 764 .WillOnce(Return(&stream2)) | 690 .WillOnce(Return(&stream2)) |
| 765 .WillOnce(Return(&stream3)); | 691 .WillOnce(Return(&stream3)); |
| 766 | 692 |
| 767 // Stream1 should be able to successfully open and start. | 693 // Stream1 should be able to successfully open and start. |
| 768 EXPECT_CALL(stream1, Open()) | 694 EXPECT_CALL(stream1, Open()) |
| 769 .WillOnce(Return(true)); | 695 .WillOnce(Return(true)); |
| 770 EXPECT_CALL(stream1, Close()); | |
| 771 EXPECT_CALL(stream1, SetVolume(_)); | 696 EXPECT_CALL(stream1, SetVolume(_)); |
| 772 EXPECT_CALL(stream2, Open()) | 697 EXPECT_CALL(stream2, Open()) |
| 773 .WillOnce(Return(true)); | 698 .WillOnce(Return(true)); |
| 774 EXPECT_CALL(stream2, SetVolume(_)); | 699 EXPECT_CALL(stream2, SetVolume(_)); |
| 775 EXPECT_CALL(stream2, Close()); | |
| 776 | 700 |
| 777 // Open and start the first proxy and stream. | 701 // Open and start the first proxy and stream. |
| 778 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_.get()); | 702 AudioOutputProxy* proxy1 = new AudioOutputProxy(resampler_.get()); |
| 779 EXPECT_TRUE(proxy1->Open()); | 703 EXPECT_TRUE(proxy1->Open()); |
| 780 proxy1->Start(&callback_); | 704 proxy1->Start(&callback_); |
| 781 OnStart(); | 705 OnStart(); |
| 782 | 706 |
| 783 // Open, but do not start the second proxy. | 707 // Open, but do not start the second proxy. |
| 784 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get()); | 708 AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get()); |
| 785 EXPECT_TRUE(proxy2->Open()); | 709 EXPECT_TRUE(proxy2->Open()); |
| 786 | 710 |
| 787 // Open, start and then stop the third proxy. | 711 // Open, start and then stop the third proxy. |
| 788 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get()); | 712 AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get()); |
| 789 EXPECT_TRUE(proxy3->Open()); | 713 EXPECT_TRUE(proxy3->Open()); |
| 790 proxy3->Start(&callback_); | 714 proxy3->Start(&callback_); |
| 791 OnStart(); | 715 OnStart(); |
| 792 proxy3->Stop(); | 716 proxy3->Stop(); |
| 793 | 717 |
| 794 // Wait for stream to timeout and shutdown. | 718 // Wait for stream to timeout and shutdown. |
| 795 WaitForCloseTimer(kTestCloseDelayMs); | 719 WaitForCloseTimer(&stream2); |
| 796 | 720 |
| 721 EXPECT_CALL(stream1, Close()); |
| 797 resampler_->CloseStreamsForWedgeFix(); | 722 resampler_->CloseStreamsForWedgeFix(); |
| 798 | 723 |
| 724 // Don't pump the MessageLoop between CloseStreamsForWedgeFix() and |
| 725 // RestartStreamsForWedgeFix() to simulate intended usage. The OnStart() call |
| 726 // will take care of necessary work. |
| 727 |
| 799 // Stream3 should take Stream1's place after RestartStreamsForWedgeFix(). No | 728 // Stream3 should take Stream1's place after RestartStreamsForWedgeFix(). No |
| 800 // additional streams should be opened for proxy2 and proxy3. | 729 // additional streams should be opened for proxy2 and proxy3. |
| 801 EXPECT_CALL(stream3, Open()) | 730 EXPECT_CALL(stream3, Open()) |
| 802 .WillOnce(Return(true)); | 731 .WillOnce(Return(true)); |
| 803 EXPECT_CALL(stream3, Close()); | |
| 804 EXPECT_CALL(stream3, SetVolume(_)); | 732 EXPECT_CALL(stream3, SetVolume(_)); |
| 805 | 733 |
| 806 resampler_->RestartStreamsForWedgeFix(); | 734 resampler_->RestartStreamsForWedgeFix(); |
| 807 OnStart(); | 735 OnStart(); |
| 808 | 736 |
| 809 // Perform the required Stop()/Close() shutdown dance for each proxy. | 737 // Perform the required Stop()/Close() shutdown dance for each proxy. |
| 810 proxy3->Close(); | 738 proxy3->Close(); |
| 811 proxy2->Close(); | 739 proxy2->Close(); |
| 812 proxy1->Stop(); | 740 proxy1->Stop(); |
| 813 proxy1->Close(); | 741 CloseAndWaitForCloseTimer(proxy1, &stream3); |
| 814 | 742 |
| 815 // Wait for all of the messages to fly and then verify stream behavior. | 743 // Wait for all of the messages to fly and then verify stream behavior. |
| 816 WaitForCloseTimer(kTestCloseDelayMs); | |
| 817 EXPECT_TRUE(stream1.stop_called()); | 744 EXPECT_TRUE(stream1.stop_called()); |
| 818 EXPECT_TRUE(stream1.start_called()); | 745 EXPECT_TRUE(stream1.start_called()); |
| 819 EXPECT_TRUE(stream2.stop_called()); | 746 EXPECT_TRUE(stream2.stop_called()); |
| 820 EXPECT_TRUE(stream2.start_called()); | 747 EXPECT_TRUE(stream2.start_called()); |
| 821 EXPECT_TRUE(stream3.stop_called()); | 748 EXPECT_TRUE(stream3.stop_called()); |
| 822 EXPECT_TRUE(stream3.start_called()); | 749 EXPECT_TRUE(stream3.start_called()); |
| 823 } | 750 } |
| 824 | 751 |
| 825 } // namespace media | 752 } // namespace media |
| OLD | NEW |