| Index: content/renderer/media/webaudio_suspender_unittest.cc
|
| diff --git a/content/renderer/media/webaudio_suspender_unittest.cc b/content/renderer/media/webaudio_suspender_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..617597765d9109a3598ee92cf260cb63266de68a
|
| --- /dev/null
|
| +++ b/content/renderer/media/webaudio_suspender_unittest.cc
|
| @@ -0,0 +1,160 @@
|
| +// Copyright 2016 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/run_loop.h"
|
| +#include "base/test/test_message_loop.h"
|
| +#include "content/renderer/media/webaudio_suspender.h"
|
| +#include "media/base/fake_audio_render_callback.h"
|
| +#include "media/base/mock_audio_renderer_sink.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace content {
|
| +
|
| +ACTION_P(RunClosure, closure) {
|
| + closure.Run();
|
| +}
|
| +
|
| +class WebAudioSuspenderTest : public testing::Test {
|
| + public:
|
| + WebAudioSuspenderTest()
|
| + : params_(media::AudioParameters::AUDIO_FAKE,
|
| + media::CHANNEL_LAYOUT_MONO,
|
| + 44100,
|
| + 8,
|
| + 128),
|
| + mock_sink_(new testing::StrictMock<media::MockAudioRendererSink>()),
|
| + fake_callback_(0.1),
|
| + temp_bus_(media::AudioBus::Create(params_)),
|
| + suspender_(&fake_callback_,
|
| + params_,
|
| + mock_sink_,
|
| + test_loop_.task_runner()) {}
|
| + ~WebAudioSuspenderTest() override {}
|
| +
|
| + protected:
|
| + base::TestMessageLoop test_loop_;
|
| + const media::AudioParameters params_;
|
| + scoped_refptr<testing::StrictMock<media::MockAudioRendererSink>> mock_sink_;
|
| + media::FakeAudioRenderCallback fake_callback_;
|
| + std::unique_ptr<media::AudioBus> temp_bus_;
|
| + WebAudioSuspender suspender_;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(WebAudioSuspenderTest);
|
| +};
|
| +
|
| +TEST_F(WebAudioSuspenderTest, BasicPassthough) {
|
| + temp_bus_->Zero();
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_FALSE(temp_bus_->AreFramesZero());
|
| +}
|
| +
|
| +TEST_F(WebAudioSuspenderTest, SuspendResumeTriggered) {
|
| + // Set a negative timeout so any silence will suspend immediately.
|
| + suspender_.set_silent_timeout_for_testing(base::TimeDelta::FromSeconds(-1));
|
| +
|
| + // Verify a normal Render() doesn't invoke suspend.
|
| + EXPECT_FALSE(suspender_.is_using_fake_sink_for_testing());
|
| + temp_bus_->Zero();
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_FALSE(temp_bus_->AreFramesZero());
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(suspender_.is_using_fake_sink_for_testing());
|
| +
|
| + // Mute all audio generated by the callback, this should suspend immediately.
|
| + fake_callback_.set_volume(0);
|
| + temp_bus_->Zero();
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_TRUE(temp_bus_->AreFramesZero());
|
| + EXPECT_CALL(*mock_sink_, Pause());
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_TRUE(suspender_.is_using_fake_sink_for_testing());
|
| +
|
| + // Unmute the audio, the FakeWorker inside |suspender_| should be running now,
|
| + // so we don't need to manually invoke Render().
|
| + fake_callback_.reset();
|
| + fake_callback_.set_volume(1);
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(*mock_sink_, Play()).WillOnce(RunClosure(run_loop.QuitClosure()));
|
| + run_loop.Run();
|
| + EXPECT_FALSE(suspender_.is_using_fake_sink_for_testing());
|
| +
|
| + // The first Render() after resume should return the first buffer which was
|
| + // not silent.
|
| + fake_callback_.reset();
|
| + std::unique_ptr<media::AudioBus> true_bus = media::AudioBus::Create(params_);
|
| + fake_callback_.Render(true_bus.get(), 0, 0);
|
| + EXPECT_FALSE(true_bus->AreFramesZero());
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_EQ(memcmp(temp_bus_->channel(0), true_bus->channel(0),
|
| + temp_bus_->frames() * sizeof(float)),
|
| + 0);
|
| +}
|
| +
|
| +TEST_F(WebAudioSuspenderTest, MultipleSuspend) {
|
| + // Set a negative timeout so any silence will suspend immediately.
|
| + suspender_.set_silent_timeout_for_testing(base::TimeDelta::FromSeconds(-1));
|
| +
|
| + // Mute all audio generated by the callback, this should suspend immediately.
|
| + fake_callback_.set_volume(0);
|
| + temp_bus_->Zero();
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_TRUE(temp_bus_->AreFramesZero());
|
| +
|
| + // A second render should only result in a single Pause() call.
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| +
|
| + EXPECT_CALL(*mock_sink_, Pause());
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_TRUE(suspender_.is_using_fake_sink_for_testing());
|
| +}
|
| +
|
| +TEST_F(WebAudioSuspenderTest, MultipleResume) {
|
| + // Set a negative timeout so any silence will suspend immediately.
|
| + suspender_.set_silent_timeout_for_testing(base::TimeDelta::FromSeconds(-1));
|
| +
|
| + // Mute all audio generated by the callback, this should suspend immediately.
|
| + fake_callback_.set_volume(0);
|
| + temp_bus_->Zero();
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_TRUE(temp_bus_->AreFramesZero());
|
| + EXPECT_CALL(*mock_sink_, Pause());
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_TRUE(suspender_.is_using_fake_sink_for_testing());
|
| +
|
| + // Unmute the data.
|
| + fake_callback_.set_volume(1);
|
| +
|
| + // Prepare our equality testers.
|
| + fake_callback_.reset();
|
| + std::unique_ptr<media::AudioBus> true_bus1 = media::AudioBus::Create(params_);
|
| + fake_callback_.Render(true_bus1.get(), 0, 0);
|
| + std::unique_ptr<media::AudioBus> true_bus2 = media::AudioBus::Create(params_);
|
| + fake_callback_.Render(true_bus2.get(), 0, 0);
|
| + EXPECT_NE(memcmp(true_bus1->channel(0), true_bus2->channel(0),
|
| + true_bus1->frames() * sizeof(float)),
|
| + 0);
|
| +
|
| + // Reset the fake callback data generation and force two Render() calls before
|
| + // the sink can transition.
|
| + fake_callback_.reset();
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(nullptr, 0, 0));
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(nullptr, 0, 0));
|
| + EXPECT_CALL(*mock_sink_, Play());
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(suspender_.is_using_fake_sink_for_testing());
|
| +
|
| + // Each render after resuming should return one of the non-silent bus.
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_EQ(memcmp(temp_bus_->channel(0), true_bus1->channel(0),
|
| + temp_bus_->frames() * sizeof(float)),
|
| + 0);
|
| + EXPECT_EQ(temp_bus_->frames(), suspender_.Render(temp_bus_.get(), 0, 0));
|
| + EXPECT_EQ(memcmp(temp_bus_->channel(0), true_bus2->channel(0),
|
| + temp_bus_->frames() * sizeof(float)),
|
| + 0);
|
| +}
|
| +
|
| +} // namespace content
|
|
|