Index: media/audio/audio_output_proxy_unittest.cc |
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5926dec6f62f959003b74491d69531989077cd3f |
--- /dev/null |
+++ b/media/audio/audio_output_proxy_unittest.cc |
@@ -0,0 +1,347 @@ |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/message_loop.h" |
+#include "base/platform_thread.h" |
+#include "media/audio/audio_output_dispatcher.h" |
+#include "media/audio/audio_output_proxy.h" |
+#include "media/audio/audio_manager.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using ::testing::_; |
+using ::testing::Mock; |
+using ::testing::Return; |
+ |
+namespace { |
+const int kTestCloseDelayMs = 100; |
+ |
+// Used in the test where we don't want a stream to be closed unexpectedly. |
+const int kTestBigCloseDelayMs = 100 * 1000; |
+} // namespace |
+ |
+class MockAudioOutputStream : public AudioOutputStream { |
+ public: |
+ MockAudioOutputStream() {} |
+ |
+ MOCK_METHOD0(Open, bool()); |
+ MOCK_METHOD1(Start, void(AudioSourceCallback* callback)); |
+ MOCK_METHOD0(Stop, void()); |
+ MOCK_METHOD1(SetVolume, void(double volume)); |
+ MOCK_METHOD1(GetVolume, void(double* volume)); |
+ MOCK_METHOD0(Close, void()); |
+}; |
+ |
+class MockAudioManager : public AudioManager { |
+ public: |
+ MockAudioManager() { }; |
+ |
+ MOCK_METHOD0(Init, void()); |
+ MOCK_METHOD0(HasAudioOutputDevices, bool()); |
+ MOCK_METHOD0(HasAudioInputDevices, bool()); |
+ MOCK_METHOD1(MakeAudioOutputStream, AudioOutputStream*( |
+ AudioParameters params)); |
+ MOCK_METHOD1(MakeAudioInputStream, AudioInputStream*( |
+ AudioParameters params)); |
+ MOCK_METHOD0(MuteAll, void()); |
+ MOCK_METHOD0(UnMuteAll, void()); |
+ MOCK_METHOD1(MakeAudioOutputStreamProxy, AudioOutputStream*( |
+ AudioParameters params)); |
+ MOCK_METHOD0(GetMessageLoop, MessageLoop*()); |
+}; |
+ |
+class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { |
+ public: |
+ MOCK_METHOD4(OnMoreData, uint32(AudioOutputStream* stream, |
+ uint8* dest, uint32 max_size, |
+ AudioBuffersState buffers_state)); |
+ MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); |
+}; |
+ |
+class AudioOutputProxyTest : public testing::Test { |
+ protected: |
+ virtual void SetUp() { |
+ EXPECT_CALL(manager_, GetMessageLoop()) |
+ .WillRepeatedly(Return(&message_loop_)); |
+ AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, 2, 44100, |
+ 16, 1024); |
+ dispatcher_ = new AudioOutputDispatcher(&manager_, params); |
+ dispatcher_->set_close_delay( |
+ base::TimeDelta::FromMilliseconds(kTestCloseDelayMs)); |
+ } |
+ |
+ virtual void TearDown() { |
+ // All paused proxies should have been destroyed at this point. |
+ EXPECT_EQ(0, dispatcher_->paused_proxies_); |
+ } |
+ |
+ MessageLoop message_loop_; |
+ scoped_refptr<AudioOutputDispatcher> dispatcher_; |
+ MockAudioManager manager_; |
+ MockAudioSourceCallback callback_; |
+}; |
+ |
+TEST_F(AudioOutputProxyTest, CreateAndClose) { |
+ AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_); |
+ proxy->Close(); |
+} |
+ |
+TEST_F(AudioOutputProxyTest, OpenAndClose) { |
+ MockAudioOutputStream stream; |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream)); |
+ EXPECT_CALL(stream, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy->Open()); |
+ proxy->Close(); |
+} |
+ |
+// Create a stream, and verify that it is closed after kTestCloseDelayMs. |
+// if it doesn't start playing. |
+TEST_F(AudioOutputProxyTest, CreateAndWait) { |
+ MockAudioOutputStream stream; |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream)); |
+ EXPECT_CALL(stream, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy->Open()); |
+ |
+ // Simulate a delay. |
+ PlatformThread::Sleep(kTestCloseDelayMs); |
+ message_loop_.RunAllPending(); |
+ |
+ // Verify expectation before calling Close(). |
+ Mock::VerifyAndClear(&stream); |
+ |
+ proxy->Close(); |
+} |
+ |
+// Create a stream, and then calls Start() and Stop(). |
+TEST_F(AudioOutputProxyTest, StartAndStop) { |
+ MockAudioOutputStream stream; |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream)); |
+ EXPECT_CALL(stream, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream, Start(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream, SetVolume(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream, Stop()) |
+ .Times(1); |
+ EXPECT_CALL(stream, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy->Open()); |
+ |
+ proxy->Start(&callback_); |
+ proxy->Stop(); |
+ |
+ proxy->Close(); |
+} |
+ |
+// Verify that the stream is closed after Stop is called. |
+TEST_F(AudioOutputProxyTest, CloseAfterStop) { |
+ MockAudioOutputStream stream; |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream)); |
+ EXPECT_CALL(stream, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream, Start(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream, SetVolume(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream, Stop()) |
+ .Times(1); |
+ EXPECT_CALL(stream, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy->Open()); |
+ |
+ proxy->Start(&callback_); |
+ proxy->Stop(); |
+ |
+ // Simulate a delay. |
+ PlatformThread::Sleep(kTestCloseDelayMs); |
+ message_loop_.RunAllPending(); |
+ |
+ // Verify expectation before calling Close(). |
+ Mock::VerifyAndClear(&stream); |
+ |
+ proxy->Close(); |
+} |
+ |
+// Create two streams, but don't start them. Only one device must be open. |
+TEST_F(AudioOutputProxyTest, TwoStreams) { |
+ MockAudioOutputStream stream; |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream)); |
+ EXPECT_CALL(stream, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_); |
+ AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy1->Open()); |
+ EXPECT_TRUE(proxy2->Open()); |
+ proxy1->Close(); |
+ proxy2->Close(); |
+} |
+ |
+// Two streams: verify that second stream is allocated when the first |
+// starts playing. |
+TEST_F(AudioOutputProxyTest, TwoStreams_OnePlaying) { |
+ MockAudioOutputStream stream1; |
+ MockAudioOutputStream stream2; |
+ |
+ dispatcher_->set_close_delay( |
+ base::TimeDelta::FromMilliseconds(kTestBigCloseDelayMs)); |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream1)) |
+ .WillOnce(Return(&stream2)); |
+ |
+ EXPECT_CALL(stream1, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream1, Start(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream1, SetVolume(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream1, Stop()) |
+ .Times(1); |
+ EXPECT_CALL(stream1, Close()) |
+ .Times(1); |
+ |
+ EXPECT_CALL(stream2, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream2, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_); |
+ AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy1->Open()); |
+ EXPECT_TRUE(proxy2->Open()); |
+ |
+ proxy1->Start(&callback_); |
+ message_loop_.RunAllPending(); |
+ proxy1->Stop(); |
+ |
+ proxy1->Close(); |
+ proxy2->Close(); |
+} |
+ |
+// Two streams, both are playing. Dispatcher should not open a third stream. |
+TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) { |
+ MockAudioOutputStream stream1; |
+ MockAudioOutputStream stream2; |
+ |
+ dispatcher_->set_close_delay( |
+ base::TimeDelta::FromMilliseconds(kTestBigCloseDelayMs)); |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream1)) |
+ .WillOnce(Return(&stream2)); |
+ |
+ EXPECT_CALL(stream1, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream1, Start(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream1, SetVolume(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream1, Stop()) |
+ .Times(1); |
+ EXPECT_CALL(stream1, Close()) |
+ .Times(1); |
+ |
+ EXPECT_CALL(stream2, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream2, Start(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream2, SetVolume(_)) |
+ .Times(1); |
+ EXPECT_CALL(stream2, Stop()) |
+ .Times(1); |
+ EXPECT_CALL(stream2, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_); |
+ AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy1->Open()); |
+ EXPECT_TRUE(proxy2->Open()); |
+ |
+ proxy1->Start(&callback_); |
+ proxy2->Start(&callback_); |
+ proxy1->Stop(); |
+ proxy2->Stop(); |
+ |
+ proxy1->Close(); |
+ proxy2->Close(); |
+} |
+ |
+// Open() method failed. |
+TEST_F(AudioOutputProxyTest, OpenFailed) { |
+ MockAudioOutputStream stream; |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream)); |
+ EXPECT_CALL(stream, Open()) |
+ .WillOnce(Return(false)); |
+ EXPECT_CALL(stream, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_); |
+ EXPECT_FALSE(proxy->Open()); |
+ proxy->Close(); |
+} |
+ |
+// Start() method failed. |
+TEST_F(AudioOutputProxyTest, StartFailed) { |
+ MockAudioOutputStream stream; |
+ |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(&stream)); |
+ EXPECT_CALL(stream, Open()) |
+ .WillOnce(Return(true)); |
+ EXPECT_CALL(stream, Close()) |
+ .Times(1); |
+ |
+ AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_); |
+ EXPECT_TRUE(proxy->Open()); |
+ |
+ // Simulate a delay. |
+ PlatformThread::Sleep(kTestCloseDelayMs); |
+ message_loop_.RunAllPending(); |
+ |
+ // Verify expectation before calling Close(). |
+ Mock::VerifyAndClear(&stream); |
+ |
+ // |stream| is closed at this point. Start() should reopen it again. |
+ EXPECT_CALL(manager_, MakeAudioOutputStream(_)) |
+ .WillOnce(Return(reinterpret_cast<AudioOutputStream*>(NULL))); |
+ |
+ EXPECT_CALL(callback_, OnError(_, _)) |
+ .Times(1); |
+ |
+ proxy->Start(&callback_); |
+ |
+ Mock::VerifyAndClear(&callback_); |
+ |
+ proxy->Close(); |
+} |