Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / renderer_host / media / audio_renderer_host_unittest.cc
blobc50430e074e2ea540346923383fabbf8c5081507
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 "media/base/media_switches.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using ::testing::_;
26 using ::testing::Assign;
27 using ::testing::DoAll;
28 using ::testing::NotNull;
30 namespace {
31 const int kRenderProcessId = 1;
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_frame_id,
46 Diverter* diverter));
47 MOCK_METHOD1(RemoveDiverter, void(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 OnNotifyStreamCreated)
90 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
91 OnNotifyStreamStateChanged)
92 IPC_MESSAGE_UNHANDLED(handled = false)
93 IPC_END_MESSAGE_MAP()
94 EXPECT_TRUE(handled);
96 delete message;
97 return true;
100 void OnNotifyStreamCreated(
101 int stream_id, base::SharedMemoryHandle handle,
102 base::SyncSocket::TransitDescriptor socket_descriptor, uint32 length) {
103 // Maps the shared memory.
104 shared_memory_.reset(new base::SharedMemory(handle, false));
105 CHECK(shared_memory_->Map(length));
106 CHECK(shared_memory_->memory());
107 shared_memory_length_ = length;
109 // Create the SyncSocket using the handle.
110 base::SyncSocket::Handle sync_socket_handle =
111 base::SyncSocket::UnwrapHandle(socket_descriptor);
112 sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
114 // And then delegate the call to the mock method.
115 OnStreamCreated(stream_id, length);
118 void OnNotifyStreamStateChanged(int stream_id,
119 media::AudioOutputIPCDelegate::State state) {
120 switch (state) {
121 case media::AudioOutputIPCDelegate::kPlaying:
122 OnStreamPlaying(stream_id);
123 break;
124 case media::AudioOutputIPCDelegate::kPaused:
125 OnStreamPaused(stream_id);
126 break;
127 case media::AudioOutputIPCDelegate::kError:
128 OnStreamError(stream_id);
129 break;
130 default:
131 FAIL() << "Unknown stream state";
132 break;
136 scoped_ptr<base::SharedMemory> shared_memory_;
137 scoped_ptr<base::SyncSocket> sync_socket_;
138 uint32 shared_memory_length_;
140 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
143 class AudioRendererHostTest : public testing::Test {
144 public:
145 AudioRendererHostTest() {
146 audio_manager_.reset(media::AudioManager::CreateForTesting());
147 base::CommandLine::ForCurrentProcess()->AppendSwitch(
148 switches::kUseFakeDeviceForMediaStream);
149 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
150 host_ = new MockAudioRendererHost(audio_manager_.get(),
151 &mirroring_manager_,
152 MediaInternals::GetInstance(),
153 media_stream_manager_.get());
155 // Simulate IPC channel connected.
156 host_->set_peer_process_for_testing(base::Process::Current());
159 ~AudioRendererHostTest() override {
160 // Simulate closing the IPC channel and give the audio thread time to close
161 // the underlying streams.
162 host_->OnChannelClosing();
163 SyncWithAudioThread();
165 // Release the reference to the mock object. The object will be destructed
166 // on message_loop_.
167 host_ = NULL;
170 protected:
171 void Create(bool unified_stream) {
172 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
174 EXPECT_CALL(mirroring_manager_,
175 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()))
176 .RetiresOnSaturation();
178 // Send a create stream message to the audio output stream and wait until
179 // we receive the created message.
180 int session_id;
181 media::AudioParameters params;
182 if (unified_stream) {
183 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
184 // pass the permission check.
185 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
186 params = media::AudioParameters(
187 media::AudioParameters::AUDIO_FAKE,
188 media::CHANNEL_LAYOUT_STEREO,
189 media::AudioParameters::kAudioCDSampleRate, 16,
190 media::AudioParameters::kAudioCDSampleRate / 10,
191 media::AudioParameters::NO_EFFECTS);
192 } else {
193 session_id = 0;
194 params = media::AudioParameters(
195 media::AudioParameters::AUDIO_FAKE,
196 media::CHANNEL_LAYOUT_STEREO,
197 media::AudioParameters::kAudioCDSampleRate, 16,
198 media::AudioParameters::kAudioCDSampleRate / 10);
200 host_->OnCreateStream(kStreamId, kRenderFrameId, session_id, params);
202 // At some point in the future, a corresponding RemoveDiverter() call must
203 // be made.
204 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
205 .RetiresOnSaturation();
206 SyncWithAudioThread();
209 void Close() {
210 // Send a message to AudioRendererHost to tell it we want to close the
211 // stream.
212 host_->OnCloseStream(kStreamId);
213 SyncWithAudioThread();
216 void Play() {
217 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
218 host_->OnPlayStream(kStreamId);
219 SyncWithAudioThread();
222 void Pause() {
223 EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId));
224 host_->OnPauseStream(kStreamId);
225 SyncWithAudioThread();
228 void SetVolume(double volume) {
229 host_->OnSetVolume(kStreamId, volume);
230 SyncWithAudioThread();
233 void SimulateError() {
234 EXPECT_EQ(1u, host_->audio_entries_.size())
235 << "Calls Create() before calling this method";
237 // Expect an error signal sent through IPC.
238 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId));
240 // Simulate an error sent from the audio device.
241 host_->ReportErrorAndClose(kStreamId);
242 SyncWithAudioThread();
244 // Expect the audio stream record is removed.
245 EXPECT_EQ(0u, host_->audio_entries_.size());
248 // SyncWithAudioThread() waits until all pending tasks on the audio thread
249 // are executed while also processing pending task in message_loop_ on the
250 // current thread. It is used to synchronize with the audio thread when we are
251 // closing an audio stream.
252 void SyncWithAudioThread() {
253 base::RunLoop().RunUntilIdle();
255 base::RunLoop run_loop;
256 audio_manager_->GetTaskRunner()->PostTask(
257 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
258 run_loop.Run();
261 private:
262 // MediaStreamManager uses a DestructionObserver, so it must outlive the
263 // TestBrowserThreadBundle.
264 scoped_ptr<MediaStreamManager> media_stream_manager_;
265 TestBrowserThreadBundle thread_bundle_;
266 scoped_ptr<media::AudioManager> audio_manager_;
267 MockAudioMirroringManager mirroring_manager_;
268 scoped_refptr<MockAudioRendererHost> host_;
270 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
273 TEST_F(AudioRendererHostTest, CreateAndClose) {
274 Create(false);
275 Close();
278 // Simulate the case where a stream is not properly closed.
279 TEST_F(AudioRendererHostTest, CreateAndShutdown) {
280 Create(false);
283 TEST_F(AudioRendererHostTest, CreatePlayAndClose) {
284 Create(false);
285 Play();
286 Close();
289 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) {
290 Create(false);
291 Play();
292 Pause();
293 Close();
296 TEST_F(AudioRendererHostTest, SetVolume) {
297 Create(false);
298 SetVolume(0.5);
299 Play();
300 Pause();
301 Close();
304 // Simulate the case where a stream is not properly closed.
305 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) {
306 Create(false);
307 Play();
310 // Simulate the case where a stream is not properly closed.
311 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) {
312 Create(false);
313 Play();
314 Pause();
317 TEST_F(AudioRendererHostTest, SimulateError) {
318 Create(false);
319 Play();
320 SimulateError();
323 // Simulate the case when an error is generated on the browser process,
324 // the audio device is closed but the render process try to close the
325 // audio stream again.
326 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
327 Create(false);
328 Play();
329 SimulateError();
330 Close();
333 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
334 Create(true);
335 Close();
338 // TODO(hclam): Add tests for data conversation in low latency mode.
340 } // namespace content