| Index: content/browser/renderer_host/media/audio_renderer_host_unittest.cc
|
| diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
|
| index e8bd79c9d28e3aa48135e9bf43b3bbae6c56e962..9f9053756ba1e20d38d51bb6bc948462b0fc9522 100644
|
| --- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
|
| +++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
|
| @@ -23,13 +23,15 @@ using ::testing::_;
|
| using ::testing::AtLeast;
|
| using ::testing::DoAll;
|
| using ::testing::InSequence;
|
| -using ::testing::InvokeWithoutArgs;
|
| +using ::testing::Invoke;
|
| using ::testing::Return;
|
| using ::testing::SaveArg;
|
| using ::testing::SetArgumentPointee;
|
|
|
| namespace content {
|
|
|
| +static const int kRenderProcessId = 1;
|
| +static const int kRenderViewId = 4;
|
| static const int kStreamId = 50;
|
|
|
| static bool IsRunningHeadless() {
|
| @@ -44,7 +46,7 @@ class MockAudioRendererHost : public AudioRendererHost {
|
| explicit MockAudioRendererHost(
|
| media::AudioManager* audio_manager,
|
| MediaObserver* media_observer)
|
| - : AudioRendererHost(audio_manager, media_observer),
|
| + : AudioRendererHost(kRenderProcessId, audio_manager, media_observer),
|
| shared_memory_length_(0) {
|
| }
|
|
|
| @@ -60,6 +62,8 @@ class MockAudioRendererHost : public AudioRendererHost {
|
| virtual ~MockAudioRendererHost() {
|
| // Make sure all audio streams have been deleted.
|
| EXPECT_TRUE(audio_entries_.empty());
|
| + // Make sure no mirroring sessions are active.
|
| + EXPECT_TRUE(mirror_sessions_.empty());
|
| }
|
|
|
| // This method is used to dispatch IPC messages to the renderer. We intercept
|
| @@ -136,6 +140,32 @@ class MockAudioRendererHost : public AudioRendererHost {
|
| DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
|
| };
|
|
|
| +class MockMirroringDestination
|
| + : public AudioRendererHost::MirroringDestination {
|
| + public:
|
| + MockMirroringDestination(media::AudioManager* audio_manager)
|
| + : audio_manager_(audio_manager) {}
|
| +
|
| + MOCK_METHOD1(AddInput,
|
| + media::AudioOutputStream*(const media::AudioParameters& params));
|
| +
|
| + media::AudioOutputStream* SimulateAddInput(
|
| + const media::AudioParameters& params) {
|
| + const media::AudioParameters fake_params(
|
| + media::AudioParameters::AUDIO_FAKE, params.channel_layout(),
|
| + params.sample_rate(), params.bits_per_sample(),
|
| + params.frames_per_buffer());
|
| + return audio_manager_->MakeAudioOutputStream(fake_params);
|
| + }
|
| +
|
| + private:
|
| + virtual ~MockMirroringDestination() {}
|
| +
|
| + media::AudioManager* const audio_manager_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MockMirroringDestination);
|
| +};
|
| +
|
| ACTION_P(QuitMessageLoop, message_loop) {
|
| message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
|
| }
|
| @@ -159,20 +189,24 @@ class AudioRendererHostTest : public testing::Test {
|
| audio_manager_.reset(media::AudioManager::Create());
|
| observer_.reset(new MockMediaObserver());
|
| host_ = new MockAudioRendererHost(audio_manager_.get(), observer_.get());
|
| -
|
| - // Expect the audio stream will be deleted.
|
| - EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId));
|
| + destination_ = new MockMirroringDestination(audio_manager_.get());
|
| + another_destination_ = new MockMirroringDestination(audio_manager_.get());
|
|
|
| // Simulate IPC channel connected.
|
| host_->OnChannelConnected(base::GetCurrentProcId());
|
| +
|
| + if (!IsRunningHeadless())
|
| + EnableRealDevice();
|
| }
|
|
|
| virtual void TearDown() {
|
| // Simulate closing the IPC channel.
|
| host_->OnChannelClosing();
|
|
|
| - // Release the reference to the mock object. The object will be destructed
|
| - // on message_loop_.
|
| + // Release the reference to the mock objects. The MockAudioRendererHost
|
| + // will be destroyed on message_loop_.
|
| + another_destination_ = NULL;
|
| + destination_ = NULL;
|
| host_ = NULL;
|
|
|
| // We need to continue running message_loop_ to complete all destructions.
|
| @@ -208,6 +242,13 @@ class AudioRendererHostTest : public testing::Test {
|
| // we receive the created message.
|
| host_->OnCreateStream(kStreamId, params, 0);
|
| message_loop_->Run();
|
| +
|
| + // Simulate the renderer process associating a stream with a render view.
|
| + host_->OnAssociateStreamWithProducer(kStreamId, kRenderViewId);
|
| + message_loop_->RunUntilIdle();
|
| +
|
| + // Expect the audio stream will be deleted at some later point.
|
| + EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId));
|
| }
|
|
|
| void Close() {
|
| @@ -224,7 +265,7 @@ class AudioRendererHostTest : public testing::Test {
|
| EXPECT_CALL(*observer_,
|
| OnSetAudioStreamPlaying(_, kStreamId, true));
|
| EXPECT_CALL(*host_, OnStreamPlaying(kStreamId))
|
| - .WillOnce(QuitMessageLoop(message_loop_.get()));
|
| + .WillRepeatedly(QuitMessageLoop(message_loop_.get()));
|
|
|
| host_->OnPlayStream(kStreamId);
|
| message_loop_->Run();
|
| @@ -248,6 +289,24 @@ class AudioRendererHostTest : public testing::Test {
|
| message_loop_->RunUntilIdle();
|
| }
|
|
|
| + void StartMirroringTo(MockMirroringDestination* dest,
|
| + int expected_inputs_seen) {
|
| + if (expected_inputs_seen > 0) {
|
| + EXPECT_CALL(*dest, AddInput(_))
|
| + .Times(expected_inputs_seen)
|
| + .WillRepeatedly(
|
| + Invoke(dest, &MockMirroringDestination::SimulateAddInput));
|
| + }
|
| +
|
| + AudioRendererHost::StartMirroring(kRenderProcessId, kRenderViewId, dest);
|
| + message_loop_->RunUntilIdle();
|
| + }
|
| +
|
| + void StopMirroringTo(MockMirroringDestination* dest) {
|
| + AudioRendererHost::StopMirroring(kRenderProcessId, kRenderViewId, dest);
|
| + message_loop_->RunUntilIdle();
|
| + }
|
| +
|
| void SimulateError() {
|
| EXPECT_CALL(*observer_,
|
| OnSetAudioStreamStatus(_, kStreamId, "error"));
|
| @@ -297,10 +356,21 @@ class AudioRendererHostTest : public testing::Test {
|
|
|
| void EnableRealDevice() { mock_stream_ = false; }
|
|
|
| + protected:
|
| + // Accessors for testing mirroring to one or two destinations.
|
| + MockMirroringDestination* destination() const {
|
| + return destination_;
|
| + }
|
| + MockMirroringDestination* another_destination() const {
|
| + return another_destination_;
|
| + }
|
| +
|
| private:
|
| bool mock_stream_;
|
| scoped_ptr<MockMediaObserver> observer_;
|
| scoped_refptr<MockAudioRendererHost> host_;
|
| + scoped_refptr<MockMirroringDestination> destination_;
|
| + scoped_refptr<MockMirroringDestination> another_destination_;
|
| scoped_ptr<MessageLoop> message_loop_;
|
| scoped_ptr<BrowserThreadImpl> io_thread_;
|
| scoped_ptr<BrowserThreadImpl> ui_thread_;
|
| @@ -310,34 +380,22 @@ class AudioRendererHostTest : public testing::Test {
|
| };
|
|
|
| TEST_F(AudioRendererHostTest, CreateAndClose) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| -
|
| Create();
|
| Close();
|
| }
|
|
|
| // Simulate the case where a stream is not properly closed.
|
| TEST_F(AudioRendererHostTest, CreateAndShutdown) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| -
|
| Create();
|
| }
|
|
|
| TEST_F(AudioRendererHostTest, CreatePlayAndClose) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| -
|
| Create();
|
| Play();
|
| Close();
|
| }
|
|
|
| TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| -
|
| Create();
|
| Play();
|
| Pause();
|
| @@ -345,9 +403,6 @@ TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) {
|
| }
|
|
|
| TEST_F(AudioRendererHostTest, SetVolume) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| -
|
| Create();
|
| SetVolume(0.5);
|
| Play();
|
| @@ -357,27 +412,97 @@ TEST_F(AudioRendererHostTest, SetVolume) {
|
|
|
| // Simulate the case where a stream is not properly closed.
|
| TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| -
|
| Create();
|
| Play();
|
| }
|
|
|
| // Simulate the case where a stream is not properly closed.
|
| TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| + Create();
|
| + Play();
|
| + Pause();
|
| +}
|
|
|
| +TEST_F(AudioRendererHostTest, MirroringOfNothing) {
|
| + StartMirroringTo(destination(), 0);
|
| + StopMirroringTo(destination());
|
| +}
|
| +
|
| +TEST_F(AudioRendererHostTest, StreamLifetimeAroundMirroringSession) {
|
| + Create();
|
| + Play();
|
| + StartMirroringTo(destination(), 1);
|
| + StopMirroringTo(destination());
|
| + Close();
|
| +}
|
| +
|
| +TEST_F(AudioRendererHostTest, PauseStreamDuringMirroringSession) {
|
| Create();
|
| Play();
|
| + StartMirroringTo(destination(), 1);
|
| Pause();
|
| + StopMirroringTo(destination());
|
| + Close();
|
| }
|
|
|
| -TEST_F(AudioRendererHostTest, SimulateError) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| +TEST_F(AudioRendererHostTest, StreamLifetimeWithinMirroringSession) {
|
| + StartMirroringTo(destination(), 1);
|
| + Create();
|
| + Play();
|
| + Close();
|
| + StopMirroringTo(destination());
|
| +}
|
| +
|
| +TEST_F(AudioRendererHostTest, StreamLifetimeAroundTwoMirroringSessions) {
|
| + Create();
|
| + Play();
|
| + StartMirroringTo(destination(), 1);
|
| + StopMirroringTo(destination());
|
| + StartMirroringTo(another_destination(), 1);
|
| + StopMirroringTo(another_destination());
|
| + Close();
|
| +}
|
| +
|
| +TEST_F(AudioRendererHostTest, StreamLifetimeWithinTwoMirroringSessions) {
|
| + StartMirroringTo(destination(), 1);
|
| + Create();
|
| + Play();
|
| + StopMirroringTo(destination());
|
| + StartMirroringTo(another_destination(), 1);
|
| + Close();
|
| + StopMirroringTo(another_destination());
|
| +}
|
|
|
| +TEST_F(AudioRendererHostTest, StreamSwitchesMirroringSessions) {
|
| + StartMirroringTo(destination(), 1);
|
| + Create();
|
| + Play();
|
| + StartMirroringTo(another_destination(), 1);
|
| + Close();
|
| + StopMirroringTo(another_destination());
|
| + StopMirroringTo(destination()); // This should be a no-op.
|
| +}
|
| +
|
| +TEST_F(AudioRendererHostTest, SwitchMirroringDestinationNoStreams) {
|
| + StartMirroringTo(destination(), 0);
|
| + StartMirroringTo(another_destination(), 0);
|
| + StopMirroringTo(another_destination());
|
| +}
|
| +
|
| +// Simulate the case where mirroring was not stopped before shutdown.
|
| +TEST_F(AudioRendererHostTest, StartMirroringNothingAndShutdown) {
|
| + StartMirroringTo(destination(), 0);
|
| +}
|
| +
|
| +// Simulate the case where mirroring was not stopped before shutdown, and a
|
| +// stream was being mirrored.
|
| +TEST_F(AudioRendererHostTest, StartMirroringSomethingAndShutdown) {
|
| + StartMirroringTo(destination(), 1);
|
| + Create();
|
| + Play();
|
| +}
|
| +
|
| +TEST_F(AudioRendererHostTest, SimulateError) {
|
| Create();
|
| Play();
|
| SimulateError();
|
| @@ -387,9 +512,6 @@ TEST_F(AudioRendererHostTest, SimulateError) {
|
| // the audio device is closed but the render process try to close the
|
| // audio stream again.
|
| TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
|
| - if (!IsRunningHeadless())
|
| - EnableRealDevice();
|
| -
|
| Create();
|
| Play();
|
| SimulateError();
|
|
|