Chromium Code Reviews| Index: media/blink/webaudiosourceprovider_impl_unittest.cc |
| diff --git a/media/blink/webaudiosourceprovider_impl_unittest.cc b/media/blink/webaudiosourceprovider_impl_unittest.cc |
| index 4a6d22ff31b1d39eb55ee7a959318e3f1d88d401..651d4adda5c0960ffb2c5a2fc5949393bc1d2a1c 100644 |
| --- a/media/blink/webaudiosourceprovider_impl_unittest.cc |
| +++ b/media/blink/webaudiosourceprovider_impl_unittest.cc |
| @@ -10,6 +10,7 @@ |
| #include "base/run_loop.h" |
| #include "media/base/audio_parameters.h" |
| #include "media/base/fake_audio_render_callback.h" |
| +#include "media/base/media_log.h" |
| #include "media/base/mock_audio_renderer_sink.h" |
| #include "media/blink/webaudiosourceprovider_impl.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| @@ -22,38 +23,73 @@ namespace media { |
| namespace { |
| const float kTestVolume = 0.25; |
| + |
| +class WebAudioSourceProviderImplUnderTest : public WebAudioSourceProviderImpl { |
| + public: |
| + WebAudioSourceProviderImplUnderTest( |
| + const scoped_refptr<SwitchableAudioRendererSink>& sink) |
|
DaleCurtis
2016/12/02 18:28:57
non const& for new code.
o1ka
2016/12/05 09:54:13
Done.
|
| + : WebAudioSourceProviderImpl(sink, new MediaLog()), |
| + fallback_sink_(new MockAudioRendererSink()) {} |
| + |
| + MockAudioRendererSink* fallback_sink() { return fallback_sink_.get(); } |
| + |
| + protected: |
| + scoped_refptr<SwitchableAudioRendererSink> CreateFallbackSink() override { |
| + return fallback_sink_; |
| + } |
| + |
| + private: |
| + ~WebAudioSourceProviderImplUnderTest() override = default; |
| + scoped_refptr<MockAudioRendererSink> fallback_sink_; |
| +}; |
|
DaleCurtis
2016/12/02 18:28:57
DISALLOW_COPY_AND_ASSIGN?
o1ka
2016/12/05 09:54:13
Done.
|
| + |
| +enum WaspSinkStatus { WASP_SINK_OK = 0, WASP_SINK_ERROR, WASP_SINK_NULL }; |
|
DaleCurtis
2016/12/02 18:28:57
I prefer enum class these days (no = 0), but up to
o1ka
2016/12/05 09:54:13
Done.
|
| + |
| +scoped_refptr<MockAudioRendererSink> CreateWaspMockSink(WaspSinkStatus status) { |
| + if (status == WASP_SINK_NULL) |
| + return nullptr; |
| + return new MockAudioRendererSink((status == WASP_SINK_OK) |
|
DaleCurtis
2016/12/02 18:28:57
No uneccesary parens.
o1ka
2016/12/05 09:54:13
Done.
|
| + ? OUTPUT_DEVICE_STATUS_OK |
| + : OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); |
| +} |
| + |
| } // namespace |
| class WebAudioSourceProviderImplTest |
| - : public testing::Test, |
| + : public testing::TestWithParam<WaspSinkStatus>, |
| public blink::WebAudioSourceProviderClient { |
| public: |
| WebAudioSourceProviderImplTest() |
| : params_(AudioParameters::AUDIO_PCM_LINEAR, |
| - CHANNEL_LAYOUT_STEREO, 48000, 16, 64), |
| + CHANNEL_LAYOUT_STEREO, |
| + 48000, |
| + 16, |
| + 64), |
| fake_callback_(0.1), |
| - mock_sink_(new MockAudioRendererSink()), |
| - wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_)) { |
| - } |
| + mock_sink_(CreateWaspMockSink(GetParam())), |
| + wasp_impl_(new WebAudioSourceProviderImplUnderTest(mock_sink_)), |
| + expected_sink_((GetParam() == WASP_SINK_OK) |
|
DaleCurtis
2016/12/02 18:28:57
Drop unnecessary parens.
o1ka
2016/12/05 09:54:13
Done.
|
| + ? mock_sink_.get() |
| + : wasp_impl_->fallback_sink()) {} |
| virtual ~WebAudioSourceProviderImplTest() {} |
| void CallAllSinkMethodsAndVerify(bool verify) { |
| testing::InSequence s; |
| - EXPECT_CALL(*mock_sink_.get(), Start()).Times(verify); |
| + EXPECT_CALL(*expected_sink_, Start()).Times(verify); |
| wasp_impl_->Start(); |
| - EXPECT_CALL(*mock_sink_.get(), Play()).Times(verify); |
| + EXPECT_CALL(*expected_sink_, Play()).Times(verify); |
| wasp_impl_->Play(); |
| - EXPECT_CALL(*mock_sink_.get(), Pause()).Times(verify); |
| + EXPECT_CALL(*expected_sink_, Pause()).Times(verify); |
| wasp_impl_->Pause(); |
| - EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)).Times(verify); |
| + EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume)).Times(verify); |
| wasp_impl_->SetVolume(kTestVolume); |
| - EXPECT_CALL(*mock_sink_.get(), Stop()).Times(verify); |
| + EXPECT_CALL(*expected_sink_, Stop()).Times(verify); |
| wasp_impl_->Stop(); |
| testing::Mock::VerifyAndClear(mock_sink_.get()); |
| @@ -63,13 +99,14 @@ class WebAudioSourceProviderImplTest |
| testing::InSequence s; |
| if (client) { |
| - EXPECT_CALL(*mock_sink_.get(), Stop()); |
| + EXPECT_CALL(*expected_sink_, Stop()); |
| EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); |
| } |
| wasp_impl_->setClient(client); |
| base::RunLoop().RunUntilIdle(); |
| testing::Mock::VerifyAndClear(mock_sink_.get()); |
| + testing::Mock::VerifyAndClear(wasp_impl_->fallback_sink()); |
| testing::Mock::VerifyAndClear(this); |
| } |
| @@ -101,21 +138,41 @@ class WebAudioSourceProviderImplTest |
| return wasp_impl_->RenderForTesting(audio_bus); |
| } |
| + void ExpectUnhealthySinkToStop() { |
| + if (GetParam() == WASP_SINK_ERROR) { |
|
DaleCurtis
2016/12/02 18:28:57
Don't need {} for single line if, but up to you.
o1ka
2016/12/05 09:54:13
Done.
|
| + EXPECT_CALL(*mock_sink_.get(), Stop()); |
| + } |
| + } |
| + |
| protected: |
| AudioParameters params_; |
| FakeAudioRenderCallback fake_callback_; |
| scoped_refptr<MockAudioRendererSink> mock_sink_; |
| - scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_; |
| + scoped_refptr<WebAudioSourceProviderImplUnderTest> wasp_impl_; |
| + MockAudioRendererSink* expected_sink_; |
| base::MessageLoop message_loop_; |
| DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest); |
| }; |
| -TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { |
| +TEST_P(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { |
| // setClient() with a NULL client should do nothing if no client is set. |
| wasp_impl_->setClient(NULL); |
| - EXPECT_CALL(*mock_sink_.get(), Stop()); |
| + // If |mock_sink_| is not null, it should be stopped during setClient(this). |
| + // If it is unhealthy, it should also be stopped during fallback in |
| + // Initialize(). |
| + if (mock_sink_) |
| + EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2 + GetParam()); |
| + |
| + wasp_impl_->setClient(this); |
| + base::RunLoop().RunUntilIdle(); |
| + |
| + if (mock_sink_) |
| + EXPECT_CALL(*mock_sink_.get(), SetVolume(1)).Times(1); |
| + wasp_impl_->setClient(NULL); |
| + base::RunLoop().RunUntilIdle(); |
| + |
| wasp_impl_->setClient(this); |
| base::RunLoop().RunUntilIdle(); |
| @@ -131,7 +188,8 @@ TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { |
| } |
| // Verify AudioRendererSink functionality w/ and w/o a client. |
| -TEST_F(WebAudioSourceProviderImplTest, SinkMethods) { |
| +TEST_P(WebAudioSourceProviderImplTest, SinkMethods) { |
| + ExpectUnhealthySinkToStop(); |
| wasp_impl_->Initialize(params_, &fake_callback_); |
| // Without a client all WASP calls should fall through to the underlying sink. |
| @@ -143,22 +201,23 @@ TEST_F(WebAudioSourceProviderImplTest, SinkMethods) { |
| CallAllSinkMethodsAndVerify(false); |
| // Removing the client should cause WASP to revert to the underlying sink. |
| - EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); |
| + EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume)); |
| SetClient(NULL); |
| CallAllSinkMethodsAndVerify(true); |
| } |
| // Verify underlying sink state is restored after client removal. |
| -TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) { |
| +TEST_P(WebAudioSourceProviderImplTest, SinkStateRestored) { |
| + ExpectUnhealthySinkToStop(); |
| wasp_impl_->Initialize(params_, &fake_callback_); |
| // Verify state set before the client is set propagates back afterward. |
| - EXPECT_CALL(*mock_sink_.get(), Start()); |
| + EXPECT_CALL(*expected_sink_, Start()); |
| wasp_impl_->Start(); |
| SetClient(this); |
| - EXPECT_CALL(*mock_sink_.get(), SetVolume(1.0)); |
| - EXPECT_CALL(*mock_sink_.get(), Start()); |
| + EXPECT_CALL(*expected_sink_, SetVolume(1.0)); |
| + EXPECT_CALL(*expected_sink_, Start()); |
| SetClient(NULL); |
| // Verify state set while the client was attached propagates back afterward. |
| @@ -166,14 +225,15 @@ TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) { |
| wasp_impl_->Play(); |
| wasp_impl_->SetVolume(kTestVolume); |
| - EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); |
| - EXPECT_CALL(*mock_sink_.get(), Start()); |
| - EXPECT_CALL(*mock_sink_.get(), Play()); |
| + EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume)); |
| + EXPECT_CALL(*expected_sink_, Start()); |
| + EXPECT_CALL(*expected_sink_, Play()); |
| SetClient(NULL); |
| } |
| // Test the AudioRendererSink state machine and its effects on provideInput(). |
| -TEST_F(WebAudioSourceProviderImplTest, ProvideInput) { |
| +TEST_P(WebAudioSourceProviderImplTest, ProvideInput) { |
| + ExpectUnhealthySinkToStop(); |
| std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_); |
| std::unique_ptr<AudioBus> bus2 = AudioBus::Create(params_); |
| @@ -259,7 +319,9 @@ TEST_F(WebAudioSourceProviderImplTest, ProvideInput) { |
| } |
| // Verify CopyAudioCB is called if registered. |
| -TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) { |
| +TEST_P(WebAudioSourceProviderImplTest, CopyAudioCB) { |
| + ExpectUnhealthySinkToStop(); |
| + |
| testing::InSequence s; |
| wasp_impl_->Initialize(params_, &fake_callback_); |
| wasp_impl_->SetCopyAudioCallback(base::Bind( |
| @@ -276,4 +338,9 @@ TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) { |
| testing::Mock::VerifyAndClear(mock_sink_.get()); |
| } |
| +INSTANTIATE_TEST_CASE_P( |
| + /* prefix intentionally left blank due to only one parameterization */, |
| + WebAudioSourceProviderImplTest, |
| + testing::Values(WASP_SINK_OK, WASP_SINK_ERROR, WASP_SINK_NULL)); |
| + |
| } // namespace media |