Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / media / media_stream_dispatcher_host_unittest.cc
blob7b6862adba3a84a56373c00757156b40a14f71b9
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 <string>
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/message_loop.h"
10 #include "base/run_loop.h"
11 #include "content/browser/browser_thread_impl.h"
12 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
13 #include "content/browser/renderer_host/media/media_stream_manager.h"
14 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
15 #include "content/browser/renderer_host/media/video_capture_manager.h"
16 #include "content/common/media/media_stream_messages.h"
17 #include "content/common/media/media_stream_options.h"
18 #include "content/public/test/mock_resource_context.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "content/test/test_content_browser_client.h"
21 #include "content/test/test_content_client.h"
22 #include "ipc/ipc_message_macros.h"
23 #include "media/audio/audio_manager.h"
24 #include "media/video/capture/fake_video_capture_device.h"
25 #include "net/url_request/url_request_context.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using ::testing::_;
30 using ::testing::DeleteArg;
31 using ::testing::DoAll;
32 using ::testing::Return;
33 using ::testing::SaveArg;
35 const int kProcessId = 5;
36 const int kRenderId = 6;
37 const int kPageRequestId = 7;
39 namespace content {
41 class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
42 public TestContentBrowserClient {
43 public:
44 MockMediaStreamDispatcherHost(
45 const scoped_refptr<base::MessageLoopProxy>& message_loop,
46 MediaStreamManager* manager)
47 : MediaStreamDispatcherHost(kProcessId, manager),
48 message_loop_(message_loop) {}
50 // A list of mock methods.
51 MOCK_METHOD4(OnStreamGenerated,
52 void(int routing_id, int request_id, int audio_array_size,
53 int video_array_size));
54 MOCK_METHOD2(OnStreamGenerationFailed, void(int routing_id, int request_id));
56 // Accessor to private functions.
57 void OnGenerateStream(int page_request_id,
58 const StreamOptions& components,
59 const base::Closure& quit_closure) {
60 quit_closure_ = quit_closure;
61 MediaStreamDispatcherHost::OnGenerateStream(
62 kRenderId, page_request_id, components, GURL());
65 void OnStopGeneratedStream(const std::string& label) {
66 MediaStreamDispatcherHost::OnStopGeneratedStream(kRenderId, label);
69 // Return the number of streams that have been opened or is being open.
70 size_t NumberOfStreams() {
71 return streams_.size();
74 std::string label_;
75 StreamDeviceInfoArray audio_devices_;
76 StreamDeviceInfoArray video_devices_;
78 private:
79 virtual ~MockMediaStreamDispatcherHost() {}
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) OVERRIDE {
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(MockMediaStreamDispatcherHost, *message)
91 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated)
92 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
93 OnStreamGenerationFailed)
94 IPC_MESSAGE_UNHANDLED(handled = false)
95 IPC_END_MESSAGE_MAP()
96 EXPECT_TRUE(handled);
98 delete message;
99 return true;
102 // These handler methods do minimal things and delegate to the mock methods.
103 void OnStreamGenerated(
104 const IPC::Message& msg,
105 int request_id,
106 std::string label,
107 StreamDeviceInfoArray audio_device_list,
108 StreamDeviceInfoArray video_device_list) {
109 OnStreamGenerated(msg.routing_id(), request_id, audio_device_list.size(),
110 video_device_list.size());
111 // Notify that the event have occured.
112 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure_));
113 label_ = label;
114 audio_devices_ = audio_device_list;
115 video_devices_ = video_device_list;
118 void OnStreamGenerationFailed(const IPC::Message& msg, int request_id) {
119 OnStreamGenerationFailed(msg.routing_id(), request_id);
120 if (!quit_closure_.is_null())
121 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure_));
122 label_= "";
125 scoped_refptr<base::MessageLoopProxy> message_loop_;
126 base::Closure quit_closure_;
129 class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
130 public:
131 MOCK_METHOD1(OnStarted, void(const base::Closure& stop));
134 class MediaStreamDispatcherHostTest : public testing::Test {
135 public:
136 MediaStreamDispatcherHostTest()
137 : old_browser_client_(NULL),
138 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
139 // Create our own MediaStreamManager.
140 audio_manager_.reset(media::AudioManager::Create());
141 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
142 // Make sure we use fake devices to avoid long delays.
143 media_stream_manager_->UseFakeDevice();
145 host_ = new MockMediaStreamDispatcherHost(base::MessageLoopProxy::current(),
146 media_stream_manager_.get());
148 // Use the fake content client and browser.
149 content_client_.reset(new TestContentClient());
150 SetContentClient(content_client_.get());
151 old_browser_client_ = SetBrowserClientForTesting(host_.get());
154 virtual ~MediaStreamDispatcherHostTest() {
155 // Recover the old browser client and content client.
156 SetBrowserClientForTesting(old_browser_client_);
157 content_client_.reset();
160 protected:
161 virtual void SetupFakeUI(bool expect_started) {
162 scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
163 if (expect_started) {
164 EXPECT_CALL(*stream_ui, OnStarted(_));
166 media_stream_manager_->UseFakeUI(
167 stream_ui.PassAs<FakeMediaStreamUIProxy>());
170 void GenerateStreamAndWaitForResult(int page_request_id,
171 const StreamOptions& options) {
172 base::RunLoop run_loop;
173 host_->OnGenerateStream(page_request_id, options, run_loop.QuitClosure());
174 run_loop.Run();
177 scoped_refptr<MockMediaStreamDispatcherHost> host_;
178 scoped_ptr<media::AudioManager> audio_manager_;
179 scoped_ptr<MediaStreamManager> media_stream_manager_;
180 ContentBrowserClient* old_browser_client_;
181 scoped_ptr<ContentClient> content_client_;
182 content::TestBrowserThreadBundle thread_bundle_;
185 TEST_F(MediaStreamDispatcherHostTest, GenerateStream) {
186 StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
188 SetupFakeUI(true);
189 EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
190 GenerateStreamAndWaitForResult(kPageRequestId, options);
192 std::string label = host_->label_;
194 EXPECT_EQ(host_->audio_devices_.size(), 0u);
195 EXPECT_EQ(host_->video_devices_.size(), 1u);
196 EXPECT_EQ(host_->NumberOfStreams(), 1u);
198 host_->OnStopGeneratedStream(label);
199 EXPECT_EQ(host_->NumberOfStreams(), 0u);
202 TEST_F(MediaStreamDispatcherHostTest, GenerateThreeStreams) {
203 // This test opens three video capture devices. Two fake devices exists and it
204 // is expected the last call to |Open()| will open the first device again, but
205 // with a different label.
206 StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
208 // Generate first stream.
209 SetupFakeUI(true);
210 EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
211 GenerateStreamAndWaitForResult(kPageRequestId, options);
213 // Check the latest generated stream.
214 EXPECT_EQ(host_->audio_devices_.size(), 0u);
215 EXPECT_EQ(host_->video_devices_.size(), 1u);
216 std::string label1 = host_->label_;
217 std::string device_id1 = host_->video_devices_.front().device.id;
219 // Check that we now have one opened streams.
220 EXPECT_EQ(host_->NumberOfStreams(), 1u);
222 // Generate second stream.
223 SetupFakeUI(true);
224 EXPECT_CALL(*host_.get(),
225 OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
226 GenerateStreamAndWaitForResult(kPageRequestId + 1, options);
228 // Check the latest generated stream.
229 EXPECT_EQ(host_->audio_devices_.size(), 0u);
230 EXPECT_EQ(host_->video_devices_.size(), 1u);
231 std::string label2 = host_->label_;
232 std::string device_id2 = host_->video_devices_.front().device.id;
233 EXPECT_EQ(device_id1, device_id2);
234 EXPECT_NE(label1, label2);
236 // Check that we now have two opened streams.
237 EXPECT_EQ(2u, host_->NumberOfStreams());
239 // Generate third stream.
240 SetupFakeUI(true);
241 EXPECT_CALL(*host_.get(),
242 OnStreamGenerated(kRenderId, kPageRequestId + 2, 0, 1));
243 GenerateStreamAndWaitForResult(kPageRequestId + 2, options);
245 // Check the latest generated stream.
246 EXPECT_EQ(host_->audio_devices_.size(), 0u);
247 EXPECT_EQ(host_->video_devices_.size(), 1u);
248 std::string label3 = host_->label_;
249 std::string device_id3 = host_->video_devices_.front().device.id;
250 EXPECT_EQ(device_id1, device_id3);
251 EXPECT_NE(label1, label3);
252 EXPECT_NE(label2, label3);
254 // Check that we now have three opened streams.
255 EXPECT_EQ(host_->NumberOfStreams(), 3u);
257 host_->OnStopGeneratedStream(label1);
258 host_->OnStopGeneratedStream(label2);
259 host_->OnStopGeneratedStream(label3);
260 EXPECT_EQ(host_->NumberOfStreams(), 0u);
263 TEST_F(MediaStreamDispatcherHostTest, FailOpenVideoDevice) {
264 StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
266 media::FakeVideoCaptureDevice::SetFailNextCreate();
267 SetupFakeUI(false);
268 EXPECT_CALL(*host_.get(),
269 OnStreamGenerationFailed(kRenderId, kPageRequestId));
270 GenerateStreamAndWaitForResult(kPageRequestId, options);
273 TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
274 StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
276 base::RunLoop run_loop;
278 // Create multiple GenerateStream requests.
279 size_t streams = 5;
280 for (size_t i = 1; i <= streams; ++i) {
281 host_->OnGenerateStream(
282 kPageRequestId + i, options, run_loop.QuitClosure());
283 EXPECT_EQ(host_->NumberOfStreams(), i);
286 // Calling OnChannelClosing() to cancel all the pending requests.
287 host_->OnChannelClosing();
288 run_loop.RunUntilIdle();
290 // Streams should have been cleaned up.
291 EXPECT_EQ(host_->NumberOfStreams(), 0u);
294 TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) {
295 StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
297 // Create first group of streams.
298 size_t generated_streams = 3;
299 for (size_t i = 0; i < generated_streams; ++i) {
300 SetupFakeUI(true);
301 EXPECT_CALL(*host_.get(),
302 OnStreamGenerated(kRenderId, kPageRequestId + i, 0, 1));
303 GenerateStreamAndWaitForResult(kPageRequestId + i, options);
305 EXPECT_EQ(host_->NumberOfStreams(), generated_streams);
307 // Calling OnChannelClosing() to cancel all the pending/generated streams.
308 host_->OnChannelClosing();
309 base::RunLoop().RunUntilIdle();
311 // Streams should have been cleaned up.
312 EXPECT_EQ(host_->NumberOfStreams(), 0u);
315 TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
316 StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
318 base::Closure close_callback;
319 scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
320 EXPECT_CALL(*stream_ui, OnStarted(_))
321 .WillOnce(SaveArg<0>(&close_callback));
322 media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
324 EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
325 EXPECT_CALL(*host_.get(),
326 OnStreamGenerationFailed(kRenderId, kPageRequestId));
327 GenerateStreamAndWaitForResult(kPageRequestId, options);
329 EXPECT_EQ(host_->audio_devices_.size(), 0u);
330 EXPECT_EQ(host_->video_devices_.size(), 1u);
331 EXPECT_EQ(host_->NumberOfStreams(), 1u);
333 ASSERT_FALSE(close_callback.is_null());
334 close_callback.Run();
335 base::RunLoop().RunUntilIdle();
337 EXPECT_EQ(host_->NumberOfStreams(), 0u);
340 }; // namespace content