Chromium Code Reviews| Index: content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
| diff --git a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
| index e3eb3b3718fd765a7fe53b509066cf3432764467..bfe5c6c8a624451bb0cd05107ab17fea84fc0dfe 100644 |
| --- a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
| +++ b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc |
| @@ -6,12 +6,12 @@ |
| #include <memory> |
| +#include "base/bind.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| -#include "content/renderer/media/audio_device_factory.h" |
| +#include "content/renderer/media/audio_renderer_sink_cache.h" |
| #include "media/audio/audio_device_description.h" |
| -#include "media/base/audio_capturer_source.h" |
| #include "media/base/audio_parameters.h" |
| #include "media/base/audio_renderer_mixer.h" |
| #include "media/base/audio_renderer_mixer_input.h" |
| @@ -23,6 +23,7 @@ |
| namespace content { |
| +namespace { |
| static const int kBitsPerChannel = 16; |
| static const int kSampleRate = 48000; |
|
Guido Urdaneta
2016/05/25 13:33:13
static is redundant in all these constants. namesp
o1ka
2016/05/25 14:52:11
Done.
|
| static const int kBufferSize = 8192; |
| @@ -37,14 +38,63 @@ static const char kNonexistentDeviceId[] = "nonexistent-device-id"; |
| static const int kRenderFrameId = 124; |
| static const int kAnotherRenderFrameId = 678; |
| +} // namespace; |
| using media::AudioParameters; |
| -class AudioRendererMixerManagerTest : public testing::Test, |
| - public AudioDeviceFactory { |
| +class FakeAudioRendererSinkCache : public AudioRendererSinkCache { |
| + public: |
| + using GetSinkCallback = |
| + base::Callback<scoped_refptr<media::AudioRendererSink>( |
| + int render_frame_id, |
| + int session_id, |
| + const std::string& device_id, |
| + const url::Origin& security_origin)>; |
| + |
| + using ReleaseSinkCallback = |
| + base::Callback<void(const media::AudioRendererSink*)>; |
| + |
| + FakeAudioRendererSinkCache(const GetSinkCallback& get_sink_cb, |
| + const ReleaseSinkCallback& release_sink_cb) |
| + : get_sink_cb_(get_sink_cb), release_sink_cb_(release_sink_cb) {} |
| + |
| + media::OutputDeviceInfo GetSinkInfo( |
| + int source_render_frame_id, |
| + int session_id, |
| + const std::string& device_id, |
| + const url::Origin& security_origin) final { |
| + return get_sink_cb_ |
| + .Run(source_render_frame_id, session_id, device_id, security_origin) |
| + ->GetOutputDeviceInfo(); |
| + } |
| + |
| + scoped_refptr<media::AudioRendererSink> GetSink( |
| + int source_render_frame_id, |
| + const std::string& device_id, |
| + const url::Origin& security_origin) final { |
| + return get_sink_cb_.Run(source_render_frame_id, 0, device_id, |
| + security_origin); |
| + } |
| + |
| + void ReleaseSink(const media::AudioRendererSink* sink) final { |
| + release_sink_cb_.Run(sink); |
| + } |
| + |
| + private: |
| + GetSinkCallback get_sink_cb_; |
| + ReleaseSinkCallback release_sink_cb_; |
| +}; |
| + |
| +class AudioRendererMixerManagerTest : public testing::Test { |
| public: |
| AudioRendererMixerManagerTest() |
| - : manager_(new AudioRendererMixerManager()), |
| + : manager_(new AudioRendererMixerManager( |
| + std::unique_ptr<AudioRendererSinkCache>( |
| + new FakeAudioRendererSinkCache( |
| + base::Bind(&AudioRendererMixerManagerTest::GetSinkPtr, |
| + base::Unretained(this)), |
| + base::Bind(&AudioRendererMixerManagerTest::ReleaseSinkPtr, |
| + base::Unretained(this)))))), |
| mock_sink_(new media::MockAudioRendererSink()), |
| mock_sink_no_device_(new media::MockAudioRendererSink( |
| kNonexistentDeviceId, |
| @@ -52,9 +102,6 @@ class AudioRendererMixerManagerTest : public testing::Test, |
| mock_sink_matched_device_( |
| new media::MockAudioRendererSink(kMatchedDeviceId, |
| media::OUTPUT_DEVICE_STATUS_OK)), |
| - mock_sink_for_session_id_( |
| - new media::MockAudioRendererSink(kMatchedDeviceId, |
| - media::OUTPUT_DEVICE_STATUS_OK)), |
| kSecurityOrigin2(GURL("http://localhost")) {} |
| media::AudioRendererMixer* GetMixer( |
| @@ -67,11 +114,11 @@ class AudioRendererMixerManagerTest : public testing::Test, |
| security_origin, device_status); |
| } |
| - void RemoveMixer(int source_render_frame_id, |
| + void ReturnMixer(int source_render_frame_id, |
| const media::AudioParameters& params, |
| const std::string& device_id, |
| const url::Origin& security_origin) { |
| - return manager_->RemoveMixer(source_render_frame_id, params, device_id, |
| + return manager_->ReturnMixer(source_render_frame_id, params, device_id, |
| security_origin); |
| } |
| @@ -81,24 +128,8 @@ class AudioRendererMixerManagerTest : public testing::Test, |
| } |
| protected: |
| - MOCK_METHOD1(CreateAudioCapturerSource, |
| - scoped_refptr<media::AudioCapturerSource>(int)); |
| - MOCK_METHOD5( |
| - CreateSwitchableAudioRendererSink, |
| - scoped_refptr<media::SwitchableAudioRendererSink>(SourceType, |
| - int, |
| - int, |
| - const std::string&, |
| - const url::Origin&)); |
| - MOCK_METHOD5(CreateAudioRendererSink, |
| - scoped_refptr<media::AudioRendererSink>(SourceType, |
| - int, |
| - int, |
| - const std::string&, |
| - const url::Origin&)); |
| - |
| - scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink( |
| - int render_frame_id, |
| + scoped_refptr<media::AudioRendererSink> GetSinkPtr( |
| + int source_render_frame_id, |
| int session_id, |
| const std::string& device_id, |
| const url::Origin& security_origin) { |
| @@ -110,7 +141,7 @@ class AudioRendererMixerManagerTest : public testing::Test, |
| return mock_sink_no_device_; |
| if (device_id.empty()) { |
| // The sink used to get device ID from session ID if it's not empty |
| - return session_id ? mock_sink_for_session_id_ : mock_sink_; |
| + return session_id ? mock_sink_matched_device_ : mock_sink_; |
| } |
| if (device_id == kMatchedDeviceId) |
| return mock_sink_matched_device_; |
| @@ -119,11 +150,13 @@ class AudioRendererMixerManagerTest : public testing::Test, |
| return nullptr; |
| } |
| + MOCK_METHOD1(ReleaseSinkPtr, void(const media::AudioRendererSink*)); |
| + |
| std::unique_ptr<AudioRendererMixerManager> manager_; |
| + |
| scoped_refptr<media::MockAudioRendererSink> mock_sink_; |
| scoped_refptr<media::MockAudioRendererSink> mock_sink_no_device_; |
| scoped_refptr<media::MockAudioRendererSink> mock_sink_matched_device_; |
| - scoped_refptr<media::MockAudioRendererSink> mock_sink_for_session_id_; |
| // To avoid global/static non-POD constants. |
| const url::Origin kSecurityOrigin; |
| @@ -133,14 +166,17 @@ class AudioRendererMixerManagerTest : public testing::Test, |
| DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest); |
| }; |
| -// Verify GetMixer() and RemoveMixer() both work as expected; particularly with |
| +// Verify GetMixer() and ReturnMixer() both work as expected; particularly with |
| // respect to the explicit ref counting done. |
| -TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) { |
| +TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) { |
| // Since we're testing two different sets of parameters, we expect |
| // AudioRendererMixerManager to call Start and Stop on our mock twice. |
| EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
| EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
| + // We expect 2 mixers to be created; each of them should release the sink. |
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| + |
| // There should be no mixers outstanding to start with. |
| EXPECT_EQ(0, mixer_count()); |
| @@ -158,8 +194,8 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) { |
| kSecurityOrigin, nullptr)); |
| EXPECT_EQ(1, mixer_count()); |
| - // Remove the extra mixer we just acquired. |
| - RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| + // Return the extra mixer we just acquired. |
| + ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(1, mixer_count()); |
| media::AudioParameters params2( |
| @@ -173,10 +209,10 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) { |
| // Different parameters should result in a different mixer1. |
| EXPECT_NE(mixer1, mixer2); |
| - // Remove both outstanding mixers. |
| - RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| + // Return both outstanding mixers. |
| + ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(1, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
| + ReturnMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(0, mixer_count()); |
| } |
| @@ -187,6 +223,9 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) { |
| EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
| EXPECT_EQ(mixer_count(), 0); |
| + // We expect 2 mixers to be created; each of them should release the sink. |
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| + |
| media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR, |
| kChannelLayout, |
| kSampleRate, |
| @@ -207,7 +246,7 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) { |
| EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params2, kDefaultDeviceId, |
| kSecurityOrigin, nullptr)); |
| EXPECT_EQ(1, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
| + ReturnMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(1, mixer_count()); |
| // Modify some parameters that do matter: channel layout |
| @@ -221,11 +260,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) { |
| EXPECT_NE(mixer1, GetMixer(kRenderFrameId, params3, kDefaultDeviceId, |
| kSecurityOrigin, nullptr)); |
| EXPECT_EQ(2, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin); |
| + ReturnMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(1, mixer_count()); |
| - // Remove final mixer. |
| - RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| + // Return final mixer. |
| + ReturnMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(0, mixer_count()); |
| } |
| @@ -239,6 +278,9 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) { |
| EXPECT_CALL(*mock_sink_.get(), Start()).Times(2); |
| EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2); |
| + // We expect 2 mixers to be created; each of them should release the sink. |
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| + |
| media::AudioParameters params( |
| AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, |
| kBitsPerChannel, kBufferSize); |
| @@ -258,7 +300,7 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) { |
| EXPECT_EQ(0, mixer_count()); |
| // Implicitly test that AudioRendererMixerInput was provided with the expected |
| - // callbacks needed to acquire an AudioRendererMixer and remove it. |
| + // callbacks needed to acquire an AudioRendererMixer and return it. |
| input->Start(); |
| EXPECT_EQ(1, mixer_count()); |
| another_input->Start(); |
| @@ -287,6 +329,10 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) { |
| EXPECT_CALL(*mock_sink_matched_device_.get(), Start()).Times(1); |
| EXPECT_CALL(*mock_sink_matched_device_.get(), Stop()).Times(1); |
| + // We expect 3 mixers to be created; each of them should release a sink. |
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2); |
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_matched_device_.get())).Times(1); |
| + |
| media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| kChannelLayout, kSampleRate, kBitsPerChannel, |
| kBufferSize); |
| @@ -323,7 +369,7 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) { |
| EXPECT_EQ(0, mixer_count()); |
| // Implicitly test that AudioRendererMixerInput was provided with the expected |
| - // callbacks needed to acquire an AudioRendererMixer and remove it. |
| + // callbacks needed to acquire an AudioRendererMixer and return it. |
| input_to_default_device->Start(); |
| EXPECT_EQ(1, mixer_count()); |
| @@ -359,6 +405,9 @@ TEST_F(AudioRendererMixerManagerTest, MixerDevices) { |
| EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3); |
| EXPECT_EQ(0, mixer_count()); |
| + // We expect 3 mixers to be created; each of them should release a sink. |
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(3); |
| + |
| media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| kChannelLayout, kSampleRate, kBitsPerChannel, |
| kBufferSize); |
| @@ -380,11 +429,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerDevices) { |
| EXPECT_NE(mixer1, mixer3); |
| EXPECT_NE(mixer2, mixer3); |
| - RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
| + ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(2, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin); |
| + ReturnMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin); |
| EXPECT_EQ(1, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2); |
| + ReturnMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2); |
| EXPECT_EQ(0, mixer_count()); |
| } |
| @@ -395,6 +444,9 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { |
| EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1); |
| EXPECT_EQ(0, mixer_count()); |
| + // We expect 1 mixers to be created; it should release its sink. |
|
Guido Urdaneta
2016/05/25 13:33:13
nit: s/mixers/mixer
o1ka
2016/05/25 14:52:11
Done.
|
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1); |
| + |
| media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| kChannelLayout, kSampleRate, kBitsPerChannel, |
| kBufferSize); |
| @@ -421,13 +473,13 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { |
| EXPECT_EQ(1, mixer_count()); |
| EXPECT_EQ(mixer1, mixer4); |
| - RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
| + ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin); |
| EXPECT_EQ(1, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin); |
| + ReturnMixer(kRenderFrameId, params, std::string(), kSecurityOrigin); |
| EXPECT_EQ(1, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2); |
| + ReturnMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2); |
| EXPECT_EQ(1, mixer_count()); |
| - RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin2); |
| + ReturnMixer(kRenderFrameId, params, std::string(), kSecurityOrigin2); |
| EXPECT_EQ(0, mixer_count()); |
| } |
| @@ -435,14 +487,19 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) { |
| // status code when a nonexistent device is requested. |
| TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) { |
| EXPECT_EQ(0, mixer_count()); |
| + |
| + // Mixer manager should release a not-ok sink when failing to create a mixer. |
| + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_no_device_.get())).Times(1); |
| + |
| media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| kChannelLayout, kSampleRate, kBitsPerChannel, |
| kBufferSize); |
| media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK; |
| - EXPECT_CALL(*mock_sink_no_device_.get(), Stop()); |
| + |
| media::AudioRendererMixer* mixer = |
| GetMixer(kRenderFrameId, params, kNonexistentDeviceId, kSecurityOrigin, |
| &device_status); |
| + |
| EXPECT_FALSE(mixer); |
| EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, device_status); |
| EXPECT_EQ(0, mixer_count()); |