Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / renderer_host / media / audio_renderer_host_unittest.cc
blob38a7f0af2d91cbf46852189bfdfc0d9aeeb3bd05
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.
5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/sync_socket.h"
10 #include "content/browser/media/capture/audio_mirroring_manager.h"
11 #include "content/browser/media/media_internals.h"
12 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
13 #include "content/browser/renderer_host/media/audio_renderer_host.h"
14 #include "content/browser/renderer_host/media/media_stream_manager.h"
15 #include "content/common/media/audio_messages.h"
16 #include "content/public/common/content_switches.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "ipc/ipc_message_utils.h"
19 #include "media/audio/audio_manager.h"
20 #include "media/base/bind_to_current_loop.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using ::testing::_;
25 using ::testing::Assign;
26 using ::testing::DoAll;
27 using ::testing::NotNull;
29 namespace {
30 const int kRenderProcessId = 1;
31 const int kRenderViewId = 4;
32 const int kRenderFrameId = 5;
33 const int kStreamId = 50;
34 } // namespace
36 namespace content {
38 class MockAudioMirroringManager : public AudioMirroringManager {
39 public:
40 MockAudioMirroringManager() {}
41 virtual ~MockAudioMirroringManager() {}
43 MOCK_METHOD3(AddDiverter,
44 void(int render_process_id,
45 int render_view_id,
46 Diverter* diverter));
47 MOCK_METHOD3(RemoveDiverter,
48 void(int render_process_id,
49 int render_view_id,
50 Diverter* diverter));
52 private:
53 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
56 class MockAudioRendererHost : public AudioRendererHost {
57 public:
58 MockAudioRendererHost(media::AudioManager* audio_manager,
59 AudioMirroringManager* mirroring_manager,
60 MediaInternals* media_internals,
61 MediaStreamManager* media_stream_manager)
62 : AudioRendererHost(kRenderProcessId,
63 audio_manager,
64 mirroring_manager,
65 media_internals,
66 media_stream_manager),
67 shared_memory_length_(0) {}
69 // A list of mock methods.
70 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
71 MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
72 MOCK_METHOD1(OnStreamPaused, void(int stream_id));
73 MOCK_METHOD1(OnStreamError, void(int stream_id));
75 private:
76 virtual ~MockAudioRendererHost() {
77 // Make sure all audio streams have been deleted.
78 EXPECT_TRUE(audio_entries_.empty());
81 // This method is used to dispatch IPC messages to the renderer. We intercept
82 // these messages here and dispatch to our mock methods to verify the
83 // conversation between this object and the renderer.
84 virtual bool Send(IPC::Message* message) {
85 CHECK(message);
87 // In this method we dispatch the messages to the according handlers as if
88 // we are the renderer.
89 bool handled = true;
90 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
91 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
92 OnStreamCreated)
93 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
94 OnStreamStateChanged)
95 IPC_MESSAGE_UNHANDLED(handled = false)
96 IPC_END_MESSAGE_MAP()
97 EXPECT_TRUE(handled);
99 delete message;
100 return true;
103 void OnStreamCreated(const IPC::Message& msg,
104 int stream_id,
105 base::SharedMemoryHandle handle,
106 #if defined(OS_WIN)
107 base::SyncSocket::Handle socket_handle,
108 #else
109 base::FileDescriptor socket_descriptor,
110 #endif
111 uint32 length) {
112 // Maps the shared memory.
113 shared_memory_.reset(new base::SharedMemory(handle, false));
114 CHECK(shared_memory_->Map(length));
115 CHECK(shared_memory_->memory());
116 shared_memory_length_ = length;
118 // Create the SyncSocket using the handle.
119 base::SyncSocket::Handle sync_socket_handle;
120 #if defined(OS_WIN)
121 sync_socket_handle = socket_handle;
122 #else
123 sync_socket_handle = socket_descriptor.fd;
124 #endif
125 sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
127 // And then delegate the call to the mock method.
128 OnStreamCreated(stream_id, length);
131 void OnStreamStateChanged(const IPC::Message& msg,
132 int stream_id,
133 media::AudioOutputIPCDelegate::State state) {
134 switch (state) {
135 case media::AudioOutputIPCDelegate::kPlaying:
136 OnStreamPlaying(stream_id);
137 break;
138 case media::AudioOutputIPCDelegate::kPaused:
139 OnStreamPaused(stream_id);
140 break;
141 case media::AudioOutputIPCDelegate::kError:
142 OnStreamError(stream_id);
143 break;
144 default:
145 FAIL() << "Unknown stream state";
146 break;
150 scoped_ptr<base::SharedMemory> shared_memory_;
151 scoped_ptr<base::SyncSocket> sync_socket_;
152 uint32 shared_memory_length_;
154 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
157 class AudioRendererHostTest : public testing::Test {
158 public:
159 AudioRendererHostTest() {
160 audio_manager_.reset(media::AudioManager::CreateForTesting());
161 CommandLine::ForCurrentProcess()->AppendSwitch(
162 switches::kUseFakeDeviceForMediaStream);
163 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
164 host_ = new MockAudioRendererHost(audio_manager_.get(),
165 &mirroring_manager_,
166 MediaInternals::GetInstance(),
167 media_stream_manager_.get());
169 // Simulate IPC channel connected.
170 host_->set_peer_pid_for_testing(base::GetCurrentProcId());
173 virtual ~AudioRendererHostTest() {
174 // Simulate closing the IPC channel and give the audio thread time to close
175 // the underlying streams.
176 host_->OnChannelClosing();
177 SyncWithAudioThread();
179 // Release the reference to the mock object. The object will be destructed
180 // on message_loop_.
181 host_ = NULL;
184 protected:
185 void Create(bool unified_stream) {
186 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
188 EXPECT_CALL(mirroring_manager_,
189 AddDiverter(kRenderProcessId, kRenderViewId, NotNull()))
190 .RetiresOnSaturation();
192 // Send a create stream message to the audio output stream and wait until
193 // we receive the created message.
194 int session_id;
195 media::AudioParameters params;
196 if (unified_stream) {
197 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
198 // pass the permission check.
199 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
200 params = media::AudioParameters(
201 media::AudioParameters::AUDIO_FAKE,
202 media::CHANNEL_LAYOUT_STEREO,
204 media::AudioParameters::kAudioCDSampleRate, 16,
205 media::AudioParameters::kAudioCDSampleRate / 10,
206 media::AudioParameters::NO_EFFECTS);
207 } else {
208 session_id = 0;
209 params = media::AudioParameters(
210 media::AudioParameters::AUDIO_FAKE,
211 media::CHANNEL_LAYOUT_STEREO,
212 media::AudioParameters::kAudioCDSampleRate, 16,
213 media::AudioParameters::kAudioCDSampleRate / 10);
215 host_->OnCreateStream(kStreamId, kRenderViewId, kRenderFrameId, session_id,
216 params);
218 // At some point in the future, a corresponding RemoveDiverter() call must
219 // be made.
220 EXPECT_CALL(mirroring_manager_,
221 RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull()))
222 .RetiresOnSaturation();
223 SyncWithAudioThread();
226 void Close() {
227 // Send a message to AudioRendererHost to tell it we want to close the
228 // stream.
229 host_->OnCloseStream(kStreamId);
230 SyncWithAudioThread();
233 void Play() {
234 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
235 host_->OnPlayStream(kStreamId);
236 SyncWithAudioThread();
239 void Pause() {
240 EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId));
241 host_->OnPauseStream(kStreamId);
242 SyncWithAudioThread();
245 void SetVolume(double volume) {
246 host_->OnSetVolume(kStreamId, volume);
247 SyncWithAudioThread();
250 void SimulateError() {
251 EXPECT_EQ(1u, host_->audio_entries_.size())
252 << "Calls Create() before calling this method";
254 // Expect an error signal sent through IPC.
255 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId));
257 // Simulate an error sent from the audio device.
258 host_->ReportErrorAndClose(kStreamId);
259 SyncWithAudioThread();
261 // Expect the audio stream record is removed.
262 EXPECT_EQ(0u, host_->audio_entries_.size());
265 // SyncWithAudioThread() waits until all pending tasks on the audio thread
266 // are executed while also processing pending task in message_loop_ on the
267 // current thread. It is used to synchronize with the audio thread when we are
268 // closing an audio stream.
269 void SyncWithAudioThread() {
270 base::RunLoop().RunUntilIdle();
272 base::RunLoop run_loop;
273 audio_manager_->GetTaskRunner()->PostTask(
274 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
275 run_loop.Run();
278 private:
279 // MediaStreamManager uses a DestructionObserver, so it must outlive the
280 // TestBrowserThreadBundle.
281 scoped_ptr<MediaStreamManager> media_stream_manager_;
282 TestBrowserThreadBundle thread_bundle_;
283 scoped_ptr<media::AudioManager> audio_manager_;
284 MockAudioMirroringManager mirroring_manager_;
285 scoped_refptr<MockAudioRendererHost> host_;
287 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
290 TEST_F(AudioRendererHostTest, CreateAndClose) {
291 Create(false);
292 Close();
295 // Simulate the case where a stream is not properly closed.
296 TEST_F(AudioRendererHostTest, CreateAndShutdown) {
297 Create(false);
300 TEST_F(AudioRendererHostTest, CreatePlayAndClose) {
301 Create(false);
302 Play();
303 Close();
306 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) {
307 Create(false);
308 Play();
309 Pause();
310 Close();
313 TEST_F(AudioRendererHostTest, SetVolume) {
314 Create(false);
315 SetVolume(0.5);
316 Play();
317 Pause();
318 Close();
321 // Simulate the case where a stream is not properly closed.
322 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) {
323 Create(false);
324 Play();
327 // Simulate the case where a stream is not properly closed.
328 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) {
329 Create(false);
330 Play();
331 Pause();
334 TEST_F(AudioRendererHostTest, SimulateError) {
335 Create(false);
336 Play();
337 SimulateError();
340 // Simulate the case when an error is generated on the browser process,
341 // the audio device is closed but the render process try to close the
342 // audio stream again.
343 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
344 Create(false);
345 Play();
346 SimulateError();
347 Close();
350 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
351 Create(true);
352 Close();
355 // TODO(hclam): Add tests for data conversation in low latency mode.
357 } // namespace content