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

Side by Side Diff: content/browser/renderer_host/media/audio_output_delegate_unittest.cc

Issue 2443573003: Factor out AudioOutputDelegate from AudioRendererHost. (Closed)
Patch Set: Rebase. Comments. Created 4 years, 1 month 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
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/media/audio_output_delegate.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/run_loop.h"
15 #include "content/browser/media/capture/audio_mirroring_manager.h"
16 #include "content/browser/renderer_host/media/media_stream_manager.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "media/audio/fake_audio_log_factory.h"
20 #include "media/audio/fake_audio_manager.h"
21 #include "media/base/media_switches.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using ::testing::_;
26 using ::testing::InSequence;
27 using ::testing::NiceMock;
28 using ::testing::NotNull;
29
30 // Not tested:
o1ka 2016/11/22 13:24:03 add "yet", it will look cooler ;)
Max Morin 2016/11/22 16:04:29 Done.
31 // - Interactions with AudioStreamMonitor (goes through WebContentsImpl,
32 // so it's a bit tricky).
33 // - Logging (small risk of bugs, not worth the effort).
34 // - That the returned socket/memory is correctly set up.
35
36 namespace content {
37
38 namespace {
39
40 const int kRenderProcessId = 1;
41 const int kRenderFrameId = 5;
42 const int kStreamId = 50;
43 const char kDefaultDeviceId[] = "";
44
45 struct MockAudioMirroringManager : public AudioMirroringManager {
46 MockAudioMirroringManager() : AudioMirroringManager() {}
o1ka 2016/11/22 13:24:03 just =default?
Max Morin 2016/11/22 16:04:29 Done.
47 virtual ~MockAudioMirroringManager() {}
o1ka 2016/11/22 13:24:03 override instead
Max Morin 2016/11/22 16:04:29 Done.
48
49 MOCK_METHOD3(AddDiverter,
50 void(int render_process_id,
51 int render_frame_id,
52 Diverter* diverter));
53 MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter));
54 };
55
56 struct MockObserver : public content::MediaObserver {
57 void OnAudioCaptureDevicesChanged() override {}
58 void OnVideoCaptureDevicesChanged() override {}
59 void OnMediaRequestStateChanged(int render_process_id,
60 int render_frame_id,
61 int page_request_id,
62 const GURL& security_origin,
63 MediaStreamType stream_type,
64 MediaRequestState state) override {}
65 void OnSetCapturingLinkSecured(int render_process_id,
66 int render_frame_id,
67 int page_request_id,
68 MediaStreamType stream_type,
69 bool is_secure) override {}
70
71 MOCK_METHOD2(OnCreatingAudioStream,
72 void(int render_process_id, int render_frame_id));
73 };
74
75 struct MockEventHandler : public AudioOutputDelegate::EventHandler {
76 MOCK_METHOD1(OnStreamStateChanged, void(bool playing));
77 MOCK_METHOD3(OnStreamCreated,
78 void(int stream_id,
79 base::SharedMemory* shared_memory,
80 base::CancelableSyncSocket* socket));
81 MOCK_METHOD1(OnStreamError, void(int stream_id));
82 };
83
84 } // namespace
85
86 class AudioOutputDelegateTest : public testing::Test {
87 public:
88 AudioOutputDelegateTest() {
89 base::CommandLine::ForCurrentProcess()->AppendSwitch(
90 switches::kUseFakeDeviceForMediaStream);
91
92 thread_bundle_ = base::MakeUnique<TestBrowserThreadBundle>(
93 TestBrowserThreadBundle::Options::REAL_IO_THREAD);
94 audio_thread_ = base::MakeUnique<base::Thread>("AudioThread");
95
96 // Audio manager creation stolen from content/browser/browser_main_loop.cc.
97 #if defined(OS_WIN)
98 audio_thread_->init_com_with_mta(true);
99 #endif // defined(OS_WIN)
100 CHECK(audio_thread_->Start());
101
102 #if defined(OS_MACOSX)
103 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner =
104 base::ThreadTaskRunnerHandle::Get();
105 #else
106 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner =
107 audio_thread_->task_runner();
108 #endif // defined(OS_MACOSX)
109
110 audio_manager_.reset(new media::FakeAudioManager(
111 audio_task_runner, audio_thread_->task_runner(), &log_factory_));
112 media_stream_manager_ =
113 base::MakeUnique<MediaStreamManager>(audio_manager_.get());
114 }
115
116 ~AudioOutputDelegateTest() override {}
117
118 AudioOutputDelegate::UniquePtr CreateDelegate() {
119 AudioOutputDelegate::UniquePtr delegate;
120 BrowserThread::PostTask(
121 BrowserThread::IO, FROM_HERE,
122 base::Bind(&AudioOutputDelegateTest::CreateDelegateOnIO,
123 base::Unretained(this), base::Unretained(&delegate)));
124 SyncWithAllThreads();
125 return delegate;
126 }
127
128 void CreateDelegateOnIO(AudioOutputDelegate::UniquePtr* delegate) {
129 *delegate = AudioOutputDelegate::Create(
130 &event_handler_, audio_manager_.get(),
131 log_factory_.CreateAudioLog(
132 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER),
133 &mirroring_manager_, &media_observer_, kStreamId, kRenderFrameId,
134 kRenderProcessId, audio_manager_->GetDefaultOutputStreamParameters(),
135 kDefaultDeviceId);
136 }
137
138 protected:
139 void SyncWithAllThreads() {
140 // New tasks might be posted while we are syncing, but in every iteration at
141 // least one task will be run. 20 iterations should be enough for our code.
142 for (int i = 0; i < 20; ++i) {
143 base::RunLoop().RunUntilIdle();
144 SyncWith(BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
145 SyncWith(audio_thread_->task_runner());
146 }
147 }
148
149 // MediaStreamManager uses a DestructionObserver, so it must outlive the
150 // TestBrowserThreadBundle.
151 std::unique_ptr<MediaStreamManager> media_stream_manager_;
152 std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
153 std::unique_ptr<base::Thread> audio_thread_;
154 media::ScopedAudioManagerPtr audio_manager_;
155 NiceMock<MockAudioMirroringManager> mirroring_manager_;
o1ka 2016/11/22 13:24:04 Question: why NiceMocks are needed here?
Max Morin 2016/11/22 16:04:29 The test output is hard to read if there is a bunc
o1ka 2016/11/22 21:48:16 But should not you set all the appropriate expecta
Max Morin 2016/11/25 15:32:35 Ok then. In my opinion, this makes it less clear w
156 NiceMock<MockEventHandler> event_handler_;
157 NiceMock<MockObserver> media_observer_;
158 media::FakeAudioLogFactory log_factory_;
159
160 private:
161 void SyncWith(scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
162 CHECK(task_runner);
163 CHECK(!task_runner->BelongsToCurrentThread());
164 base::WaitableEvent e = {base::WaitableEvent::ResetPolicy::MANUAL,
165 base::WaitableEvent::InitialState::NOT_SIGNALED};
166 task_runner->PostTask(FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
167 base::Unretained(&e)));
168 e.Wait();
169 }
170
171 DISALLOW_COPY_AND_ASSIGN(AudioOutputDelegateTest);
172 };
173
174 TEST_F(AudioOutputDelegateTest, Create_AlertsObserver) {
175 EXPECT_CALL(media_observer_,
176 OnCreatingAudioStream(kRenderProcessId, kRenderFrameId))
177 .Times(1);
178
179 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
o1ka 2016/11/22 13:24:03 On which thread delegates are created in real life
Max Morin 2016/11/22 16:04:29 Yes. This method actually created them on the IO t
180 // Delete delegate on IO thread:
181 BrowserThread::PostTask(
182 BrowserThread::IO, FROM_HERE,
183 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
184 base::Passed(std::move(delegate))));
185 SyncWithAllThreads();
186 }
187
188 TEST_F(AudioOutputDelegateTest, Create_CallsHandler) {
189 EXPECT_CALL(event_handler_, OnStreamCreated(kStreamId, NotNull(), NotNull()));
190
191 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
192 BrowserThread::PostTask(
193 BrowserThread::IO, FROM_HERE,
194 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
195 base::Passed(std::move(delegate))));
196 SyncWithAllThreads();
197 }
198
199 TEST_F(AudioOutputDelegateTest,
200 Create_RegistersAndUnregistersControllerWithMirroringManager) {
201 {
202 InSequence s;
203 EXPECT_CALL(mirroring_manager_,
204 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()))
205 .Times(1);
206 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())).Times(1);
207 }
208
209 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
210 BrowserThread::PostTask(
211 BrowserThread::IO, FROM_HERE,
212 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
213 base::Passed(std::move(delegate))));
214 SyncWithAllThreads();
215 }
216
217 TEST_F(AudioOutputDelegateTest, Play_CallsHandler) {
218 {
219 InSequence s;
220 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
221 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
222 }
223
224 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
225 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
226 base::Bind(&AudioOutputDelegate::OnPlayStream,
227 base::Unretained(delegate.get())));
228 SyncWithAllThreads();
229 BrowserThread::PostTask(
230 BrowserThread::IO, FROM_HERE,
231 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
232 base::Passed(std::move(delegate))));
233 SyncWithAllThreads();
234 }
235
236 TEST_F(AudioOutputDelegateTest, PlayAndDestroy_DoesNotCallHandler) {
237 EXPECT_CALL(event_handler_, OnStreamStateChanged(_)).Times(0);
238
239 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
240 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
241 base::Bind(
242 [](AudioOutputDelegate::UniquePtr delegate) {
243 delegate->OnPlayStream();
244 delegate.reset();
245 },
246 base::Passed(std::move(delegate))));
247 SyncWithAllThreads();
248 }
249
250 TEST_F(AudioOutputDelegateTest, Error_CallsHandler) {
251 EXPECT_CALL(event_handler_, OnStreamError(kStreamId)).Times(1);
252
253 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
254 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
255 base::Bind(&media::AudioOutputController::OnError,
256 delegate->controller(), nullptr));
257 SyncWithAllThreads();
258 BrowserThread::PostTask(
259 BrowserThread::IO, FROM_HERE,
260 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
261 base::Passed(std::move(delegate))));
262 SyncWithAllThreads();
263 }
264
265 TEST_F(AudioOutputDelegateTest, ErrorAndDestroy_DoesNotCallHandler) {
266 EXPECT_CALL(event_handler_, OnStreamError(kStreamId)).Times(0);
267
268 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
269 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
270 base::Bind(
271 [](AudioOutputDelegate::UniquePtr delegate) {
272 delegate->controller()->OnError(nullptr);
273 delegate.reset();
274 },
275 base::Passed(std::move(delegate))));
276 SyncWithAllThreads();
277 }
278
279 TEST_F(AudioOutputDelegateTest, PlayPause_CallsHandlerCorrectNumberOfTimes) {
280 {
281 InSequence s;
282 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
283 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
284 }
285
286 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
287 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
288 base::Bind(&AudioOutputDelegate::OnPlayStream,
289 base::Unretained(delegate.get())));
290 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
291 base::Bind(&AudioOutputDelegate::OnPauseStream,
292 base::Unretained(delegate.get())));
293 SyncWithAllThreads();
294 BrowserThread::PostTask(
295 BrowserThread::IO, FROM_HERE,
296 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
297 base::Passed(std::move(delegate))));
298 SyncWithAllThreads();
299 }
300
301 TEST_F(AudioOutputDelegateTest,
302 PlayPausePlay_CallsHandlerCorrectNumberOfTimes) {
303 {
304 InSequence s;
305 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
306 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
307 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
308 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
309 }
310
311 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
312 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
313 base::Bind(&AudioOutputDelegate::OnPlayStream,
314 base::Unretained(delegate.get())));
315 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
316 base::Bind(&AudioOutputDelegate::OnPauseStream,
317 base::Unretained(delegate.get())));
318 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
319 base::Bind(&AudioOutputDelegate::OnPlayStream,
320 base::Unretained(delegate.get())));
321 SyncWithAllThreads();
322 BrowserThread::PostTask(
323 BrowserThread::IO, FROM_HERE,
324 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
325 base::Passed(std::move(delegate))));
326 SyncWithAllThreads();
327 }
328
329 TEST_F(AudioOutputDelegateTest, PlayPlay_CallsHandlerCorrectNumberOfTimes) {
330 {
331 InSequence s;
332 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
333 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
334 }
335
336 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
337 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
338 base::Bind(&AudioOutputDelegate::OnPlayStream,
339 base::Unretained(delegate.get())));
340 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
341 base::Bind(&AudioOutputDelegate::OnPlayStream,
342 base::Unretained(delegate.get())));
343 SyncWithAllThreads();
344 BrowserThread::PostTask(
345 BrowserThread::IO, FROM_HERE,
346 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
347 base::Passed(std::move(delegate))));
348 SyncWithAllThreads();
349 }
350
351 TEST_F(AudioOutputDelegateTest, Pause_DoesNotCallHandler) {
o1ka 2016/11/22 13:24:03 Naming needs clarification
Max Morin 2016/11/22 16:04:29 Done.
352 EXPECT_CALL(event_handler_, OnStreamStateChanged(_)).Times(0);
353
354 AudioOutputDelegate::UniquePtr delegate = CreateDelegate();
355 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
356 base::Bind(&AudioOutputDelegate::OnPauseStream,
357 base::Unretained(delegate.get())));
358 SyncWithAllThreads();
359 BrowserThread::PostTask(
360 BrowserThread::IO, FROM_HERE,
361 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
362 base::Passed(std::move(delegate))));
363 SyncWithAllThreads();
364 }
365
366 TEST_F(AudioOutputDelegateTest, CreateAndDestroy_DoesNotCallHandler) {
367 EXPECT_CALL(event_handler_, OnStreamCreated(_, _, _)).Times(0);
368
369 AudioOutputDelegate::UniquePtr delegate;
370 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
371 base::Bind(
372 [](AudioOutputDelegateTest* test) {
373 AudioOutputDelegate::UniquePtr delegate;
374 test->CreateDelegateOnIO(&delegate);
375 },
376 base::Unretained(this)));
377 SyncWithAllThreads();
378 }
379 } // namespace content
o1ka 2016/11/22 13:24:03 I'm not sure if various cases of destruction seque
Max Morin 2016/11/22 16:04:29 There are cases for various events being in progre
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698