Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/macros.h" | 8 #include "base/macros.h" |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| 11 #include "media/base/audio_parameters.h" | 11 #include "media/base/audio_parameters.h" |
| 12 #include "media/base/fake_audio_render_callback.h" | 12 #include "media/base/fake_audio_render_callback.h" |
| 13 #include "media/base/media_log.h" | |
| 13 #include "media/base/mock_audio_renderer_sink.h" | 14 #include "media/base/mock_audio_renderer_sink.h" |
| 14 #include "media/blink/webaudiosourceprovider_impl.h" | 15 #include "media/blink/webaudiosourceprovider_impl.h" |
| 15 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" | 18 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" |
| 18 | 19 |
| 19 using ::testing::_; | 20 using ::testing::_; |
| 20 | 21 |
| 21 namespace media { | 22 namespace media { |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 const float kTestVolume = 0.25; | 25 const float kTestVolume = 0.25; |
| 26 | |
| 27 class WebAudioSourceProviderImplUnderTest : public WebAudioSourceProviderImpl { | |
| 28 public: | |
| 29 WebAudioSourceProviderImplUnderTest( | |
| 30 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.
| |
| 31 : WebAudioSourceProviderImpl(sink, new MediaLog()), | |
| 32 fallback_sink_(new MockAudioRendererSink()) {} | |
| 33 | |
| 34 MockAudioRendererSink* fallback_sink() { return fallback_sink_.get(); } | |
| 35 | |
| 36 protected: | |
| 37 scoped_refptr<SwitchableAudioRendererSink> CreateFallbackSink() override { | |
| 38 return fallback_sink_; | |
| 39 } | |
| 40 | |
| 41 private: | |
| 42 ~WebAudioSourceProviderImplUnderTest() override = default; | |
| 43 scoped_refptr<MockAudioRendererSink> fallback_sink_; | |
| 44 }; | |
|
DaleCurtis
2016/12/02 18:28:57
DISALLOW_COPY_AND_ASSIGN?
o1ka
2016/12/05 09:54:13
Done.
| |
| 45 | |
| 46 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.
| |
| 47 | |
| 48 scoped_refptr<MockAudioRendererSink> CreateWaspMockSink(WaspSinkStatus status) { | |
| 49 if (status == WASP_SINK_NULL) | |
| 50 return nullptr; | |
| 51 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.
| |
| 52 ? OUTPUT_DEVICE_STATUS_OK | |
| 53 : OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); | |
| 54 } | |
| 55 | |
| 25 } // namespace | 56 } // namespace |
| 26 | 57 |
| 27 class WebAudioSourceProviderImplTest | 58 class WebAudioSourceProviderImplTest |
| 28 : public testing::Test, | 59 : public testing::TestWithParam<WaspSinkStatus>, |
| 29 public blink::WebAudioSourceProviderClient { | 60 public blink::WebAudioSourceProviderClient { |
| 30 public: | 61 public: |
| 31 WebAudioSourceProviderImplTest() | 62 WebAudioSourceProviderImplTest() |
| 32 : params_(AudioParameters::AUDIO_PCM_LINEAR, | 63 : params_(AudioParameters::AUDIO_PCM_LINEAR, |
| 33 CHANNEL_LAYOUT_STEREO, 48000, 16, 64), | 64 CHANNEL_LAYOUT_STEREO, |
| 65 48000, | |
| 66 16, | |
| 67 64), | |
| 34 fake_callback_(0.1), | 68 fake_callback_(0.1), |
| 35 mock_sink_(new MockAudioRendererSink()), | 69 mock_sink_(CreateWaspMockSink(GetParam())), |
| 36 wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_)) { | 70 wasp_impl_(new WebAudioSourceProviderImplUnderTest(mock_sink_)), |
| 37 } | 71 expected_sink_((GetParam() == WASP_SINK_OK) |
|
DaleCurtis
2016/12/02 18:28:57
Drop unnecessary parens.
o1ka
2016/12/05 09:54:13
Done.
| |
| 72 ? mock_sink_.get() | |
| 73 : wasp_impl_->fallback_sink()) {} | |
| 38 | 74 |
| 39 virtual ~WebAudioSourceProviderImplTest() {} | 75 virtual ~WebAudioSourceProviderImplTest() {} |
| 40 | 76 |
| 41 void CallAllSinkMethodsAndVerify(bool verify) { | 77 void CallAllSinkMethodsAndVerify(bool verify) { |
| 42 testing::InSequence s; | 78 testing::InSequence s; |
| 43 | 79 |
| 44 EXPECT_CALL(*mock_sink_.get(), Start()).Times(verify); | 80 EXPECT_CALL(*expected_sink_, Start()).Times(verify); |
| 45 wasp_impl_->Start(); | 81 wasp_impl_->Start(); |
| 46 | 82 |
| 47 EXPECT_CALL(*mock_sink_.get(), Play()).Times(verify); | 83 EXPECT_CALL(*expected_sink_, Play()).Times(verify); |
| 48 wasp_impl_->Play(); | 84 wasp_impl_->Play(); |
| 49 | 85 |
| 50 EXPECT_CALL(*mock_sink_.get(), Pause()).Times(verify); | 86 EXPECT_CALL(*expected_sink_, Pause()).Times(verify); |
| 51 wasp_impl_->Pause(); | 87 wasp_impl_->Pause(); |
| 52 | 88 |
| 53 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)).Times(verify); | 89 EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume)).Times(verify); |
| 54 wasp_impl_->SetVolume(kTestVolume); | 90 wasp_impl_->SetVolume(kTestVolume); |
| 55 | 91 |
| 56 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(verify); | 92 EXPECT_CALL(*expected_sink_, Stop()).Times(verify); |
| 57 wasp_impl_->Stop(); | 93 wasp_impl_->Stop(); |
| 58 | 94 |
| 59 testing::Mock::VerifyAndClear(mock_sink_.get()); | 95 testing::Mock::VerifyAndClear(mock_sink_.get()); |
| 60 } | 96 } |
| 61 | 97 |
| 62 void SetClient(blink::WebAudioSourceProviderClient* client) { | 98 void SetClient(blink::WebAudioSourceProviderClient* client) { |
| 63 testing::InSequence s; | 99 testing::InSequence s; |
| 64 | 100 |
| 65 if (client) { | 101 if (client) { |
| 66 EXPECT_CALL(*mock_sink_.get(), Stop()); | 102 EXPECT_CALL(*expected_sink_, Stop()); |
| 67 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); | 103 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); |
| 68 } | 104 } |
| 69 wasp_impl_->setClient(client); | 105 wasp_impl_->setClient(client); |
| 70 base::RunLoop().RunUntilIdle(); | 106 base::RunLoop().RunUntilIdle(); |
| 71 | 107 |
| 72 testing::Mock::VerifyAndClear(mock_sink_.get()); | 108 testing::Mock::VerifyAndClear(mock_sink_.get()); |
| 109 testing::Mock::VerifyAndClear(wasp_impl_->fallback_sink()); | |
| 73 testing::Mock::VerifyAndClear(this); | 110 testing::Mock::VerifyAndClear(this); |
| 74 } | 111 } |
| 75 | 112 |
| 76 bool CompareBusses(const AudioBus* bus1, const AudioBus* bus2) { | 113 bool CompareBusses(const AudioBus* bus1, const AudioBus* bus2) { |
| 77 EXPECT_EQ(bus1->channels(), bus2->channels()); | 114 EXPECT_EQ(bus1->channels(), bus2->channels()); |
| 78 EXPECT_EQ(bus1->frames(), bus2->frames()); | 115 EXPECT_EQ(bus1->frames(), bus2->frames()); |
| 79 for (int ch = 0; ch < bus1->channels(); ++ch) { | 116 for (int ch = 0; ch < bus1->channels(); ++ch) { |
| 80 if (memcmp(bus1->channel(ch), bus2->channel(ch), | 117 if (memcmp(bus1->channel(ch), bus2->channel(ch), |
| 81 sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) { | 118 sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) { |
| 82 return false; | 119 return false; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 94 void OnAudioBus(std::unique_ptr<AudioBus> bus, | 131 void OnAudioBus(std::unique_ptr<AudioBus> bus, |
| 95 uint32_t frames_delayed, | 132 uint32_t frames_delayed, |
| 96 int sample_rate) { | 133 int sample_rate) { |
| 97 DoCopyAudioCB(bus.get(), frames_delayed, sample_rate); | 134 DoCopyAudioCB(bus.get(), frames_delayed, sample_rate); |
| 98 } | 135 } |
| 99 | 136 |
| 100 int Render(AudioBus* audio_bus) { | 137 int Render(AudioBus* audio_bus) { |
| 101 return wasp_impl_->RenderForTesting(audio_bus); | 138 return wasp_impl_->RenderForTesting(audio_bus); |
| 102 } | 139 } |
| 103 | 140 |
| 141 void ExpectUnhealthySinkToStop() { | |
| 142 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.
| |
| 143 EXPECT_CALL(*mock_sink_.get(), Stop()); | |
| 144 } | |
| 145 } | |
| 146 | |
| 104 protected: | 147 protected: |
| 105 AudioParameters params_; | 148 AudioParameters params_; |
| 106 FakeAudioRenderCallback fake_callback_; | 149 FakeAudioRenderCallback fake_callback_; |
| 107 scoped_refptr<MockAudioRendererSink> mock_sink_; | 150 scoped_refptr<MockAudioRendererSink> mock_sink_; |
| 108 scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_; | 151 scoped_refptr<WebAudioSourceProviderImplUnderTest> wasp_impl_; |
| 152 MockAudioRendererSink* expected_sink_; | |
| 109 base::MessageLoop message_loop_; | 153 base::MessageLoop message_loop_; |
| 110 | 154 |
| 111 DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest); | 155 DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest); |
| 112 }; | 156 }; |
| 113 | 157 |
| 114 TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { | 158 TEST_P(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { |
| 115 // setClient() with a NULL client should do nothing if no client is set. | 159 // setClient() with a NULL client should do nothing if no client is set. |
| 116 wasp_impl_->setClient(NULL); | 160 wasp_impl_->setClient(NULL); |
| 117 | 161 |
| 118 EXPECT_CALL(*mock_sink_.get(), Stop()); | 162 // If |mock_sink_| is not null, it should be stopped during setClient(this). |
| 163 // If it is unhealthy, it should also be stopped during fallback in | |
| 164 // Initialize(). | |
| 165 if (mock_sink_) | |
| 166 EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2 + GetParam()); | |
| 167 | |
| 119 wasp_impl_->setClient(this); | 168 wasp_impl_->setClient(this); |
| 120 base::RunLoop().RunUntilIdle(); | 169 base::RunLoop().RunUntilIdle(); |
| 121 | 170 |
| 171 if (mock_sink_) | |
| 172 EXPECT_CALL(*mock_sink_.get(), SetVolume(1)).Times(1); | |
| 173 wasp_impl_->setClient(NULL); | |
| 174 base::RunLoop().RunUntilIdle(); | |
| 175 | |
| 176 wasp_impl_->setClient(this); | |
| 177 base::RunLoop().RunUntilIdle(); | |
| 178 | |
| 122 // When Initialize() is called after setClient(), the params should propagate | 179 // When Initialize() is called after setClient(), the params should propagate |
| 123 // to the client via setFormat() during the call. | 180 // to the client via setFormat() during the call. |
| 124 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); | 181 EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); |
| 125 wasp_impl_->Initialize(params_, &fake_callback_); | 182 wasp_impl_->Initialize(params_, &fake_callback_); |
| 126 base::RunLoop().RunUntilIdle(); | 183 base::RunLoop().RunUntilIdle(); |
| 127 | 184 |
| 128 // setClient() with the same client should do nothing. | 185 // setClient() with the same client should do nothing. |
| 129 wasp_impl_->setClient(this); | 186 wasp_impl_->setClient(this); |
| 130 base::RunLoop().RunUntilIdle(); | 187 base::RunLoop().RunUntilIdle(); |
| 131 } | 188 } |
| 132 | 189 |
| 133 // Verify AudioRendererSink functionality w/ and w/o a client. | 190 // Verify AudioRendererSink functionality w/ and w/o a client. |
| 134 TEST_F(WebAudioSourceProviderImplTest, SinkMethods) { | 191 TEST_P(WebAudioSourceProviderImplTest, SinkMethods) { |
| 192 ExpectUnhealthySinkToStop(); | |
| 135 wasp_impl_->Initialize(params_, &fake_callback_); | 193 wasp_impl_->Initialize(params_, &fake_callback_); |
| 136 | 194 |
| 137 // Without a client all WASP calls should fall through to the underlying sink. | 195 // Without a client all WASP calls should fall through to the underlying sink. |
| 138 CallAllSinkMethodsAndVerify(true); | 196 CallAllSinkMethodsAndVerify(true); |
| 139 | 197 |
| 140 // With a client no calls should reach the Stop()'d sink. Also, setClient() | 198 // With a client no calls should reach the Stop()'d sink. Also, setClient() |
| 141 // should propagate the params provided during Initialize() at call time. | 199 // should propagate the params provided during Initialize() at call time. |
| 142 SetClient(this); | 200 SetClient(this); |
| 143 CallAllSinkMethodsAndVerify(false); | 201 CallAllSinkMethodsAndVerify(false); |
| 144 | 202 |
| 145 // Removing the client should cause WASP to revert to the underlying sink. | 203 // Removing the client should cause WASP to revert to the underlying sink. |
| 146 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); | 204 EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume)); |
| 147 SetClient(NULL); | 205 SetClient(NULL); |
| 148 CallAllSinkMethodsAndVerify(true); | 206 CallAllSinkMethodsAndVerify(true); |
| 149 } | 207 } |
| 150 | 208 |
| 151 // Verify underlying sink state is restored after client removal. | 209 // Verify underlying sink state is restored after client removal. |
| 152 TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) { | 210 TEST_P(WebAudioSourceProviderImplTest, SinkStateRestored) { |
| 211 ExpectUnhealthySinkToStop(); | |
| 153 wasp_impl_->Initialize(params_, &fake_callback_); | 212 wasp_impl_->Initialize(params_, &fake_callback_); |
| 154 | 213 |
| 155 // Verify state set before the client is set propagates back afterward. | 214 // Verify state set before the client is set propagates back afterward. |
| 156 EXPECT_CALL(*mock_sink_.get(), Start()); | 215 EXPECT_CALL(*expected_sink_, Start()); |
| 157 wasp_impl_->Start(); | 216 wasp_impl_->Start(); |
| 158 SetClient(this); | 217 SetClient(this); |
| 159 | 218 |
| 160 EXPECT_CALL(*mock_sink_.get(), SetVolume(1.0)); | 219 EXPECT_CALL(*expected_sink_, SetVolume(1.0)); |
| 161 EXPECT_CALL(*mock_sink_.get(), Start()); | 220 EXPECT_CALL(*expected_sink_, Start()); |
| 162 SetClient(NULL); | 221 SetClient(NULL); |
| 163 | 222 |
| 164 // Verify state set while the client was attached propagates back afterward. | 223 // Verify state set while the client was attached propagates back afterward. |
| 165 SetClient(this); | 224 SetClient(this); |
| 166 wasp_impl_->Play(); | 225 wasp_impl_->Play(); |
| 167 wasp_impl_->SetVolume(kTestVolume); | 226 wasp_impl_->SetVolume(kTestVolume); |
| 168 | 227 |
| 169 EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); | 228 EXPECT_CALL(*expected_sink_, SetVolume(kTestVolume)); |
| 170 EXPECT_CALL(*mock_sink_.get(), Start()); | 229 EXPECT_CALL(*expected_sink_, Start()); |
| 171 EXPECT_CALL(*mock_sink_.get(), Play()); | 230 EXPECT_CALL(*expected_sink_, Play()); |
| 172 SetClient(NULL); | 231 SetClient(NULL); |
| 173 } | 232 } |
| 174 | 233 |
| 175 // Test the AudioRendererSink state machine and its effects on provideInput(). | 234 // Test the AudioRendererSink state machine and its effects on provideInput(). |
| 176 TEST_F(WebAudioSourceProviderImplTest, ProvideInput) { | 235 TEST_P(WebAudioSourceProviderImplTest, ProvideInput) { |
| 236 ExpectUnhealthySinkToStop(); | |
| 177 std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_); | 237 std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_); |
| 178 std::unique_ptr<AudioBus> bus2 = AudioBus::Create(params_); | 238 std::unique_ptr<AudioBus> bus2 = AudioBus::Create(params_); |
| 179 | 239 |
| 180 // Point the WebVector into memory owned by |bus1|. | 240 // Point the WebVector into memory owned by |bus1|. |
| 181 blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels())); | 241 blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels())); |
| 182 for (size_t i = 0; i < audio_data.size(); ++i) | 242 for (size_t i = 0; i < audio_data.size(); ++i) |
| 183 audio_data[i] = bus1->channel(static_cast<int>(i)); | 243 audio_data[i] = bus1->channel(static_cast<int>(i)); |
| 184 | 244 |
| 185 // Verify provideInput() works before Initialize() and returns silence. | 245 // Verify provideInput() works before Initialize() and returns silence. |
| 186 bus1->channel(0)[0] = 1; | 246 bus1->channel(0)[0] = 1; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 | 312 |
| 253 // Stop() should return silence. | 313 // Stop() should return silence. |
| 254 wasp_impl_->Stop(); | 314 wasp_impl_->Stop(); |
| 255 bus1->channel(0)[0] = 1; | 315 bus1->channel(0)[0] = 1; |
| 256 bus2->Zero(); | 316 bus2->Zero(); |
| 257 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); | 317 wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); |
| 258 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); | 318 ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); |
| 259 } | 319 } |
| 260 | 320 |
| 261 // Verify CopyAudioCB is called if registered. | 321 // Verify CopyAudioCB is called if registered. |
| 262 TEST_F(WebAudioSourceProviderImplTest, CopyAudioCB) { | 322 TEST_P(WebAudioSourceProviderImplTest, CopyAudioCB) { |
| 323 ExpectUnhealthySinkToStop(); | |
| 324 | |
| 263 testing::InSequence s; | 325 testing::InSequence s; |
| 264 wasp_impl_->Initialize(params_, &fake_callback_); | 326 wasp_impl_->Initialize(params_, &fake_callback_); |
| 265 wasp_impl_->SetCopyAudioCallback(base::Bind( | 327 wasp_impl_->SetCopyAudioCallback(base::Bind( |
| 266 &WebAudioSourceProviderImplTest::OnAudioBus, base::Unretained(this))); | 328 &WebAudioSourceProviderImplTest::OnAudioBus, base::Unretained(this))); |
| 267 | 329 |
| 268 const std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_); | 330 const std::unique_ptr<AudioBus> bus1 = AudioBus::Create(params_); |
| 269 EXPECT_CALL(*this, DoCopyAudioCB(_, 0, params_.sample_rate())).Times(1); | 331 EXPECT_CALL(*this, DoCopyAudioCB(_, 0, params_.sample_rate())).Times(1); |
| 270 Render(bus1.get()); | 332 Render(bus1.get()); |
| 271 | 333 |
| 272 wasp_impl_->ClearCopyAudioCallback(); | 334 wasp_impl_->ClearCopyAudioCallback(); |
| 273 EXPECT_CALL(*this, DoCopyAudioCB(_, _, _)).Times(0); | 335 EXPECT_CALL(*this, DoCopyAudioCB(_, _, _)).Times(0); |
| 274 Render(bus1.get()); | 336 Render(bus1.get()); |
| 275 | 337 |
| 276 testing::Mock::VerifyAndClear(mock_sink_.get()); | 338 testing::Mock::VerifyAndClear(mock_sink_.get()); |
| 277 } | 339 } |
| 278 | 340 |
| 341 INSTANTIATE_TEST_CASE_P( | |
| 342 /* prefix intentionally left blank due to only one parameterization */, | |
| 343 WebAudioSourceProviderImplTest, | |
| 344 testing::Values(WASP_SINK_OK, WASP_SINK_ERROR, WASP_SINK_NULL)); | |
| 345 | |
| 279 } // namespace media | 346 } // namespace media |
| OLD | NEW |