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

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

Issue 2443573003: Factor out AudioOutputDelegate from AudioRendererHost. (Closed)
Patch Set: . 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 yet tested:
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() = default;
47 ~MockAudioMirroringManager() override = default;
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);
o1ka 2016/11/22 21:48:16 Add a comment on why this threading setup is chose
Max Morin 2016/11/25 15:32:35 Done.
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 = default;
117
118 AudioOutputDelegate::UniquePtr CreateDelegateOnIOAndSync() {
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_;
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, CreateAndDelete) {
175 EXPECT_CALL(media_observer_,
176 OnCreatingAudioStream(kRenderProcessId, kRenderFrameId))
177 .Times(1);
178 EXPECT_CALL(event_handler_, OnStreamCreated(kStreamId, NotNull(), NotNull()));
179 EXPECT_CALL(mirroring_manager_,
180 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()))
181 .Times(1);
182
183 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
184
185 SyncWithAllThreads();
186 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())).Times(1);
187
188 // Delete delegate on IO thread:
189 BrowserThread::PostTask(
190 BrowserThread::IO, FROM_HERE,
191 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
192 base::Passed(std::move(delegate))));
193 SyncWithAllThreads();
194 }
195
196 TEST_F(AudioOutputDelegateTest, Play_CallsHandler) {
197 {
198 InSequence s;
199 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
200 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
201 }
202
203 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
204 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
205 base::Bind(&AudioOutputDelegate::OnPlayStream,
206 base::Unretained(delegate.get())));
207 SyncWithAllThreads();
208 BrowserThread::PostTask(
o1ka 2016/11/22 21:48:16 I still think it does not make sense to post each
Max Morin 2016/11/25 15:32:35 I fixed this now.
209 BrowserThread::IO, FROM_HERE,
210 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
211 base::Passed(std::move(delegate))));
212 SyncWithAllThreads();
213 }
214
215 TEST_F(AudioOutputDelegateTest, PlayAndDestroy_DoesNotCallHandler) {
216 EXPECT_CALL(event_handler_, OnStreamStateChanged(_)).Times(0);
217
218 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
219 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
220 base::Bind(
221 [](AudioOutputDelegate::UniquePtr delegate) {
222 delegate->OnPlayStream();
223 delegate.reset();
224 },
225 base::Passed(std::move(delegate))));
226 SyncWithAllThreads();
227 }
228
229 TEST_F(AudioOutputDelegateTest, Error_CallsHandler) {
230 EXPECT_CALL(event_handler_, OnStreamError(kStreamId)).Times(1);
231
232 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
233 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
234 base::Bind(&media::AudioOutputController::OnError,
235 delegate->controller(), nullptr));
236 SyncWithAllThreads();
237 BrowserThread::PostTask(
238 BrowserThread::IO, FROM_HERE,
239 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
240 base::Passed(std::move(delegate))));
241 SyncWithAllThreads();
242 }
243
244 TEST_F(AudioOutputDelegateTest, ErrorAndDestroy_DoesNotCallHandler) {
245 EXPECT_CALL(event_handler_, OnStreamError(kStreamId)).Times(0);
246
247 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
248 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
249 base::Bind(
250 [](AudioOutputDelegate::UniquePtr delegate) {
251 delegate->controller()->OnError(nullptr);
252 delegate.reset();
253 },
254 base::Passed(std::move(delegate))));
255 SyncWithAllThreads();
256 }
257
258 TEST_F(AudioOutputDelegateTest, PlayPause_CallsHandlerCorrectNumberOfTimes) {
259 {
260 InSequence s;
261 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
262 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
263 }
264
265 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
266 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
267 base::Bind(&AudioOutputDelegate::OnPlayStream,
268 base::Unretained(delegate.get())));
269 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
270 base::Bind(&AudioOutputDelegate::OnPauseStream,
271 base::Unretained(delegate.get())));
272 SyncWithAllThreads();
273 BrowserThread::PostTask(
274 BrowserThread::IO, FROM_HERE,
275 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
276 base::Passed(std::move(delegate))));
277 SyncWithAllThreads();
278 }
279
280 TEST_F(AudioOutputDelegateTest,
281 PlayPausePlay_CallsHandlerCorrectNumberOfTimes) {
282 {
283 InSequence s;
284 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
285 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
286 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
287 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
288 }
289
290 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
291 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
292 base::Bind(&AudioOutputDelegate::OnPlayStream,
293 base::Unretained(delegate.get())));
294 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
295 base::Bind(&AudioOutputDelegate::OnPauseStream,
296 base::Unretained(delegate.get())));
297 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
298 base::Bind(&AudioOutputDelegate::OnPlayStream,
299 base::Unretained(delegate.get())));
300 SyncWithAllThreads();
301 BrowserThread::PostTask(
302 BrowserThread::IO, FROM_HERE,
303 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
304 base::Passed(std::move(delegate))));
305 SyncWithAllThreads();
306 }
307
308 TEST_F(AudioOutputDelegateTest, PlayPlay_CallsHandlerCorrectNumberOfTimes) {
309 {
310 InSequence s;
311 EXPECT_CALL(event_handler_, OnStreamStateChanged(true)).Times(1);
312 EXPECT_CALL(event_handler_, OnStreamStateChanged(false)).Times(1);
313 }
314
315 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
316 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
317 base::Bind(&AudioOutputDelegate::OnPlayStream,
318 base::Unretained(delegate.get())));
319 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
320 base::Bind(&AudioOutputDelegate::OnPlayStream,
321 base::Unretained(delegate.get())));
322 SyncWithAllThreads();
323 BrowserThread::PostTask(
324 BrowserThread::IO, FROM_HERE,
325 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
326 base::Passed(std::move(delegate))));
327 SyncWithAllThreads();
328 }
329
330 TEST_F(AudioOutputDelegateTest,
331 PauseAfterCreation_DoesNotCallOnStreamStateChanged) {
332 EXPECT_CALL(event_handler_, OnStreamStateChanged(_)).Times(0);
333
334 AudioOutputDelegate::UniquePtr delegate = CreateDelegateOnIOAndSync();
335 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
336 base::Bind(&AudioOutputDelegate::OnPauseStream,
337 base::Unretained(delegate.get())));
338 SyncWithAllThreads();
339 BrowserThread::PostTask(
340 BrowserThread::IO, FROM_HERE,
341 base::Bind([](AudioOutputDelegate::UniquePtr delegate) {},
342 base::Passed(std::move(delegate))));
343 SyncWithAllThreads();
344 }
345
346 TEST_F(AudioOutputDelegateTest, CreateAndDestroy_DoesNotCallHandler) {
347 EXPECT_CALL(event_handler_, OnStreamCreated(_, _, _)).Times(0);
348
349 AudioOutputDelegate::UniquePtr delegate;
350 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
351 base::Bind(
352 [](AudioOutputDelegateTest* test) {
353 AudioOutputDelegate::UniquePtr delegate;
354 test->CreateDelegateOnIO(&delegate);
355 },
356 base::Unretained(this)));
357 SyncWithAllThreads();
358 }
359
360 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698