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