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