Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(731)

Side by Side Diff: media/blink/webaudiosourceprovider_impl_unittest.cc

Issue 2533443002: fallback to null sink in WebAudioSourceProvider::Initialize() + UMA stats for device status (Closed)
Patch Set: content unittest fix Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698