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

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

Issue 11413078: Tab Audio Capture: Browser-side connect/disconnect functionality. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added guard against reentrancy in AudioMirroringManager methods. Created 7 years, 11 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/environment.h" 6 #include "base/environment.h"
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/process_util.h" 9 #include "base/process_util.h"
10 #include "base/sync_socket.h" 10 #include "base/sync_socket.h"
11 #include "content/browser/browser_thread_impl.h" 11 #include "content/browser/browser_thread_impl.h"
12 #include "content/browser/renderer_host/media/audio_mirroring_manager.h"
12 #include "content/browser/renderer_host/media/audio_renderer_host.h" 13 #include "content/browser/renderer_host/media/audio_renderer_host.h"
13 #include "content/browser/renderer_host/media/mock_media_observer.h" 14 #include "content/browser/renderer_host/media/mock_media_observer.h"
14 #include "content/common/media/audio_messages.h" 15 #include "content/common/media/audio_messages.h"
15 #include "ipc/ipc_message_utils.h" 16 #include "ipc/ipc_message_utils.h"
16 #include "media/audio/audio_manager.h" 17 #include "media/audio/audio_manager.h"
17 #include "media/audio/fake_audio_output_stream.h" 18 #include "media/audio/fake_audio_output_stream.h"
18 #include "net/url_request/url_request_context.h" 19 #include "net/url_request/url_request_context.h"
19 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
21 22
22 using ::testing::_; 23 using ::testing::_;
23 using ::testing::AtLeast; 24 using ::testing::AtLeast;
24 using ::testing::DoAll; 25 using ::testing::DoAll;
25 using ::testing::InSequence; 26 using ::testing::InSequence;
26 using ::testing::InvokeWithoutArgs; 27 using ::testing::NotNull;
27 using ::testing::Return; 28 using ::testing::Return;
28 using ::testing::SaveArg; 29 using ::testing::SaveArg;
29 using ::testing::SetArgumentPointee; 30 using ::testing::SetArgumentPointee;
30 31
31 namespace content { 32 namespace content {
32 33
34 static const int kRenderProcessId = 1;
35 static const int kRenderViewId = 4;
33 static const int kStreamId = 50; 36 static const int kStreamId = 50;
34 37
35 static bool IsRunningHeadless() { 38 class MockAudioMirroringManager : public AudioMirroringManager {
36 scoped_ptr<base::Environment> env(base::Environment::Create()); 39 public:
37 if (env->HasVar("CHROME_HEADLESS")) 40 MockAudioMirroringManager() {}
38 return true; 41 virtual ~MockAudioMirroringManager() {}
39 return false; 42
40 } 43 MOCK_METHOD3(AddDiverter,
44 void(int render_process_id, int render_view_id,
45 Diverter* diverter));
46 MOCK_METHOD3(RemoveDiverter,
47 void(int render_process_id, int render_view_id,
48 Diverter* diverter));
49
50 private:
51 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
52 };
41 53
42 class MockAudioRendererHost : public AudioRendererHost { 54 class MockAudioRendererHost : public AudioRendererHost {
43 public: 55 public:
44 explicit MockAudioRendererHost( 56 explicit MockAudioRendererHost(
45 media::AudioManager* audio_manager, 57 media::AudioManager* audio_manager,
58 AudioMirroringManager* mirroring_manager,
46 MediaObserver* media_observer) 59 MediaObserver* media_observer)
47 : AudioRendererHost(audio_manager, media_observer), 60 : AudioRendererHost(
61 kRenderProcessId, audio_manager, mirroring_manager, media_observer),
48 shared_memory_length_(0) { 62 shared_memory_length_(0) {
49 } 63 }
50 64
51 // A list of mock methods. 65 // A list of mock methods.
52 MOCK_METHOD2(OnStreamCreated, 66 MOCK_METHOD2(OnStreamCreated,
53 void(int stream_id, int length)); 67 void(int stream_id, int length));
54 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); 68 MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
55 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); 69 MOCK_METHOD1(OnStreamPaused, void(int stream_id));
56 MOCK_METHOD1(OnStreamError, void(int stream_id)); 70 MOCK_METHOD1(OnStreamError, void(int stream_id));
57 MOCK_METHOD2(OnStreamVolume, void(int stream_id, double volume)); 71 MOCK_METHOD2(OnStreamVolume, void(int stream_id, double volume));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 149
136 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); 150 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
137 }; 151 };
138 152
139 ACTION_P(QuitMessageLoop, message_loop) { 153 ACTION_P(QuitMessageLoop, message_loop) {
140 message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); 154 message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
141 } 155 }
142 156
143 class AudioRendererHostTest : public testing::Test { 157 class AudioRendererHostTest : public testing::Test {
144 public: 158 public:
145 AudioRendererHostTest() 159 AudioRendererHostTest() {}
146 : mock_stream_(true) {
147 }
148 160
149 protected: 161 protected:
150 virtual void SetUp() { 162 virtual void SetUp() {
151 // Create a message loop so AudioRendererHost can use it. 163 // Create a message loop so AudioRendererHost can use it.
152 message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); 164 message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
153 165
154 // Claim to be on both the UI and IO threads to pass all the DCHECKS. 166 // Claim to be on both the UI and IO threads to pass all the DCHECKS.
155 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, 167 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
156 message_loop_.get())); 168 message_loop_.get()));
157 ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI, 169 ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
158 message_loop_.get())); 170 message_loop_.get()));
159 audio_manager_.reset(media::AudioManager::Create()); 171 audio_manager_.reset(media::AudioManager::Create());
160 observer_.reset(new MockMediaObserver()); 172 observer_.reset(new MockMediaObserver());
161 host_ = new MockAudioRendererHost(audio_manager_.get(), observer_.get()); 173 host_ = new MockAudioRendererHost(
162 174 audio_manager_.get(), &mirroring_manager_, observer_.get());
163 // Expect the audio stream will be deleted.
164 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId));
165 175
166 // Simulate IPC channel connected. 176 // Simulate IPC channel connected.
167 host_->OnChannelConnected(base::GetCurrentProcId()); 177 host_->OnChannelConnected(base::GetCurrentProcId());
168 } 178 }
169 179
170 virtual void TearDown() { 180 virtual void TearDown() {
171 // Simulate closing the IPC channel. 181 // Simulate closing the IPC channel.
172 host_->OnChannelClosing(); 182 host_->OnChannelClosing();
173 183
174 // Release the reference to the mock object. The object will be destructed 184 // Release the reference to the mock object. The object will be destructed
(...skipping 11 matching lines...) Expand all
186 196
187 void Create() { 197 void Create() {
188 EXPECT_CALL(*observer_, 198 EXPECT_CALL(*observer_,
189 OnSetAudioStreamStatus(_, kStreamId, "created")); 199 OnSetAudioStreamStatus(_, kStreamId, "created"));
190 200
191 InSequence s; 201 InSequence s;
192 // We will first receive an OnStreamCreated() signal. 202 // We will first receive an OnStreamCreated() signal.
193 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)) 203 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _))
194 .WillOnce(QuitMessageLoop(message_loop_.get())); 204 .WillOnce(QuitMessageLoop(message_loop_.get()));
195 205
196 media::AudioParameters::Format format;
197 if (mock_stream_)
198 format = media::AudioParameters::AUDIO_FAKE;
199 else
200 format = media::AudioParameters::AUDIO_PCM_LINEAR;
201
202 media::AudioParameters params(
203 format, media::CHANNEL_LAYOUT_STEREO,
204 media::AudioParameters::kAudioCDSampleRate, 16,
205 media::AudioParameters::kAudioCDSampleRate / 10);
206
207 // Send a create stream message to the audio output stream and wait until 206 // Send a create stream message to the audio output stream and wait until
208 // we receive the created message. 207 // we receive the created message.
209 host_->OnCreateStream(kStreamId, params, 0); 208 host_->OnCreateStream(kStreamId,
209 media::AudioParameters(
210 media::AudioParameters::AUDIO_FAKE,
211 media::CHANNEL_LAYOUT_STEREO,
212 media::AudioParameters::kAudioCDSampleRate, 16,
213 media::AudioParameters::kAudioCDSampleRate / 10),
214 0);
210 message_loop_->Run(); 215 message_loop_->Run();
216
217 // Simulate the renderer process associating a stream with a render view.
218 EXPECT_CALL(mirroring_manager_,
219 RemoveDiverter(kRenderProcessId, MSG_ROUTING_NONE, _))
220 .RetiresOnSaturation();
221 EXPECT_CALL(mirroring_manager_,
222 AddDiverter(kRenderProcessId, kRenderViewId, NotNull()))
223 .RetiresOnSaturation();
224 host_->OnAssociateStreamWithProducer(kStreamId, kRenderViewId);
225 message_loop_->RunUntilIdle();
226 // At some point in the future, a corresponding RemoveDiverter() call must
227 // be made.
228 EXPECT_CALL(mirroring_manager_,
229 RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull()))
230 .RetiresOnSaturation();
231
232 // Expect the audio stream will be deleted at some later point.
233 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId));
211 } 234 }
212 235
213 void Close() { 236 void Close() {
214 EXPECT_CALL(*observer_, 237 EXPECT_CALL(*observer_,
215 OnSetAudioStreamStatus(_, kStreamId, "closed")); 238 OnSetAudioStreamStatus(_, kStreamId, "closed"));
216 239
217 // Send a message to AudioRendererHost to tell it we want to close the 240 // Send a message to AudioRendererHost to tell it we want to close the
218 // stream. 241 // stream.
219 host_->OnCloseStream(kStreamId); 242 host_->OnCloseStream(kStreamId);
220 message_loop_->RunUntilIdle(); 243 message_loop_->RunUntilIdle();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 void SyncWithAudioThread() { 311 void SyncWithAudioThread() {
289 // Don't use scoped_refptr to addref the media::AudioManager when posting 312 // Don't use scoped_refptr to addref the media::AudioManager when posting
290 // to the thread that itself owns. 313 // to the thread that itself owns.
291 message_loop_->PostTask( 314 message_loop_->PostTask(
292 FROM_HERE, base::Bind(&PostQuitOnAudioThread, 315 FROM_HERE, base::Bind(&PostQuitOnAudioThread,
293 base::Unretained(audio_manager_.get()), 316 base::Unretained(audio_manager_.get()),
294 message_loop_.get())); 317 message_loop_.get()));
295 message_loop_->Run(); 318 message_loop_->Run();
296 } 319 }
297 320
298 void EnableRealDevice() { mock_stream_ = false; }
299
300 private: 321 private:
301 bool mock_stream_;
302 scoped_ptr<MockMediaObserver> observer_; 322 scoped_ptr<MockMediaObserver> observer_;
323 MockAudioMirroringManager mirroring_manager_;
303 scoped_refptr<MockAudioRendererHost> host_; 324 scoped_refptr<MockAudioRendererHost> host_;
304 scoped_ptr<MessageLoop> message_loop_; 325 scoped_ptr<MessageLoop> message_loop_;
305 scoped_ptr<BrowserThreadImpl> io_thread_; 326 scoped_ptr<BrowserThreadImpl> io_thread_;
306 scoped_ptr<BrowserThreadImpl> ui_thread_; 327 scoped_ptr<BrowserThreadImpl> ui_thread_;
307 scoped_ptr<media::AudioManager> audio_manager_; 328 scoped_ptr<media::AudioManager> audio_manager_;
308 329
309 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 330 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
310 }; 331 };
311 332
312 TEST_F(AudioRendererHostTest, CreateAndClose) { 333 TEST_F(AudioRendererHostTest, CreateAndClose) {
313 if (!IsRunningHeadless())
314 EnableRealDevice();
315
316 Create(); 334 Create();
317 Close(); 335 Close();
318 } 336 }
319 337
320 // Simulate the case where a stream is not properly closed. 338 // Simulate the case where a stream is not properly closed.
321 TEST_F(AudioRendererHostTest, CreateAndShutdown) { 339 TEST_F(AudioRendererHostTest, CreateAndShutdown) {
322 if (!IsRunningHeadless())
323 EnableRealDevice();
324
325 Create(); 340 Create();
326 } 341 }
327 342
328 TEST_F(AudioRendererHostTest, CreatePlayAndClose) { 343 TEST_F(AudioRendererHostTest, CreatePlayAndClose) {
329 if (!IsRunningHeadless())
330 EnableRealDevice();
331
332 Create(); 344 Create();
333 Play(); 345 Play();
334 Close(); 346 Close();
335 } 347 }
336 348
337 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) { 349 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) {
338 if (!IsRunningHeadless())
339 EnableRealDevice();
340
341 Create(); 350 Create();
342 Play(); 351 Play();
343 Pause(); 352 Pause();
344 Close(); 353 Close();
345 } 354 }
346 355
347 TEST_F(AudioRendererHostTest, SetVolume) { 356 TEST_F(AudioRendererHostTest, SetVolume) {
348 if (!IsRunningHeadless())
349 EnableRealDevice();
350
351 Create(); 357 Create();
352 SetVolume(0.5); 358 SetVolume(0.5);
353 Play(); 359 Play();
354 Pause(); 360 Pause();
355 Close(); 361 Close();
356 } 362 }
357 363
358 // Simulate the case where a stream is not properly closed. 364 // Simulate the case where a stream is not properly closed.
359 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) { 365 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) {
360 if (!IsRunningHeadless())
361 EnableRealDevice();
362
363 Create(); 366 Create();
364 Play(); 367 Play();
365 } 368 }
366 369
367 // Simulate the case where a stream is not properly closed. 370 // Simulate the case where a stream is not properly closed.
368 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) { 371 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) {
369 if (!IsRunningHeadless())
370 EnableRealDevice();
371
372 Create(); 372 Create();
373 Play(); 373 Play();
374 Pause(); 374 Pause();
375 } 375 }
376 376
377 TEST_F(AudioRendererHostTest, SimulateError) { 377 TEST_F(AudioRendererHostTest, SimulateError) {
378 if (!IsRunningHeadless())
379 EnableRealDevice();
380
381 Create(); 378 Create();
382 Play(); 379 Play();
383 SimulateError(); 380 SimulateError();
384 } 381 }
385 382
386 // Simulate the case when an error is generated on the browser process, 383 // Simulate the case when an error is generated on the browser process,
387 // the audio device is closed but the render process try to close the 384 // the audio device is closed but the render process try to close the
388 // audio stream again. 385 // audio stream again.
389 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { 386 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
390 if (!IsRunningHeadless())
391 EnableRealDevice();
392
393 Create(); 387 Create();
394 Play(); 388 Play();
395 SimulateError(); 389 SimulateError();
396 Close(); 390 Close();
397 } 391 }
398 392
399 // TODO(hclam): Add tests for data conversation in low latency mode. 393 // TODO(hclam): Add tests for data conversation in low latency mode.
400 394
401 } // namespace content 395 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698