Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: content/browser/renderer_host/media/video_capture_host_unittest.cc

Issue 2435393003: Rename VideoCaptureHostTest to VideoCaptureTest to reflect what it is (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "content/browser/renderer_host/media/video_capture_host.h"
6
7 #include <stdint.h>
8
9 #include <map>
10 #include <memory>
11 #include <string>
12
13 #include "base/bind.h"
14 #include "base/command_line.h"
15 #include "base/location.h"
16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/run_loop.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "build/build_config.h"
22 #include "content/browser/browser_thread_impl.h"
23 #include "content/browser/renderer_host/media/media_stream_manager.h"
24 #include "content/browser/renderer_host/media/media_stream_requester.h"
25 #include "content/browser/renderer_host/media/video_capture_manager.h"
26 #include "content/public/common/content_switches.h"
27 #include "content/public/test/mock_resource_context.h"
28 #include "content/public/test/test_browser_context.h"
29 #include "content/public/test/test_browser_thread_bundle.h"
30 #include "content/test/test_content_browser_client.h"
31 #include "media/audio/mock_audio_manager.h"
32 #include "media/base/media_switches.h"
33 #include "media/base/video_capture_types.h"
34 #include "mojo/public/cpp/bindings/binding.h"
35 #include "net/url_request/url_request_context.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38
39 using ::testing::_;
40 using ::testing::AnyNumber;
41 using ::testing::DoAll;
42 using ::testing::InSequence;
43 using ::testing::Mock;
44 using ::testing::Return;
45 using ::testing::SaveArg;
46 using ::testing::StrictMock;
47
48 namespace content {
49
50 // Id used to identify the capture session between renderer and
51 // video_capture_host. This is an arbitrary value.
52 static const int kDeviceId = 555;
53
54 class MockMediaStreamRequester : public MediaStreamRequester {
55 public:
56 MockMediaStreamRequester() {}
57 virtual ~MockMediaStreamRequester() {}
58
59 // MediaStreamRequester implementation.
60 MOCK_METHOD5(StreamGenerated,
61 void(int render_frame_id,
62 int page_request_id,
63 const std::string& label,
64 const StreamDeviceInfoArray& audio_devices,
65 const StreamDeviceInfoArray& video_devices));
66 MOCK_METHOD3(StreamGenerationFailed,
67 void(int render_frame_id,
68 int page_request_id,
69 content::MediaStreamRequestResult result));
70 MOCK_METHOD3(DeviceStopped, void(int render_frame_id,
71 const std::string& label,
72 const StreamDeviceInfo& device));
73 MOCK_METHOD4(DevicesEnumerated, void(int render_frame_id,
74 int page_request_id,
75 const std::string& label,
76 const StreamDeviceInfoArray& devices));
77 MOCK_METHOD4(DeviceOpened, void(int render_frame_id,
78 int page_request_id,
79 const std::string& label,
80 const StreamDeviceInfo& device_info));
81 MOCK_METHOD1(DevicesChanged, void(MediaStreamType type));
82
83 private:
84 DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester);
85 };
86
87 ACTION_P2(ExitMessageLoop, task_runner, quit_closure) {
88 task_runner->PostTask(FROM_HERE, quit_closure);
89 }
90
91 // This is an integration test of VideoCaptureHost in conjunction with
92 // MediaStreamManager, VideoCaptureManager, VideoCaptureController, and
93 // VideoCaptureDevice.
94 class VideoCaptureHostTest : public testing::Test,
95 public mojom::VideoCaptureObserver {
96 public:
97 VideoCaptureHostTest()
98 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
99 audio_manager_(
100 new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get())),
101 task_runner_(base::ThreadTaskRunnerHandle::Get()),
102 opened_session_id_(kInvalidMediaCaptureSessionId),
103 observer_binding_(this) {}
104
105 void SetUp() override {
106 SetBrowserClientForTesting(&browser_client_);
107
108 base::CommandLine::ForCurrentProcess()->AppendSwitch(
109 switches::kUseFakeDeviceForMediaStream);
110 base::CommandLine::ForCurrentProcess()->AppendSwitch(
111 switches::kUseFakeUIForMediaStream);
112 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
113
114 // Create a Host and connect it to a simulated IPC channel.
115 host_.reset(new VideoCaptureHost(media_stream_manager_.get()));
116
117 OpenSession();
118 }
119
120 void TearDown() override {
121 Mock::VerifyAndClearExpectations(host_.get());
122 EXPECT_TRUE(host_->controllers_.empty());
123
124 CloseSession();
125
126 // Release the reference to the mock object. The object will be destructed
127 // on the current message loop.
128 host_ = nullptr;
129 }
130
131 void OpenSession() {
132 const int render_process_id = 1;
133 const int render_frame_id = 1;
134 const int page_request_id = 1;
135 const url::Origin security_origin(GURL("http://test.com"));
136
137 ASSERT_TRUE(opened_device_label_.empty());
138
139 // Enumerate video devices.
140 StreamDeviceInfoArray devices;
141 {
142 base::RunLoop run_loop;
143 std::string label = media_stream_manager_->EnumerateDevices(
144 &stream_requester_,
145 render_process_id,
146 render_frame_id,
147 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
148 page_request_id,
149 MEDIA_DEVICE_VIDEO_CAPTURE,
150 security_origin);
151 EXPECT_CALL(stream_requester_,
152 DevicesEnumerated(render_frame_id, page_request_id, label, _))
153 .Times(1)
154 .WillOnce(DoAll(ExitMessageLoop(task_runner_, run_loop.QuitClosure()),
155 SaveArg<3>(&devices)));
156 run_loop.Run();
157 Mock::VerifyAndClearExpectations(&stream_requester_);
158 media_stream_manager_->CancelRequest(label);
159 }
160 ASSERT_FALSE(devices.empty());
161 ASSERT_EQ(StreamDeviceInfo::kNoId, devices[0].session_id);
162
163 // Open the first device.
164 {
165 base::RunLoop run_loop;
166 StreamDeviceInfo opened_device;
167 media_stream_manager_->OpenDevice(
168 &stream_requester_,
169 render_process_id,
170 render_frame_id,
171 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
172 page_request_id,
173 devices[0].device.id,
174 MEDIA_DEVICE_VIDEO_CAPTURE,
175 security_origin);
176 EXPECT_CALL(stream_requester_,
177 DeviceOpened(render_frame_id, page_request_id, _, _))
178 .Times(1)
179 .WillOnce(DoAll(ExitMessageLoop(task_runner_, run_loop.QuitClosure()),
180 SaveArg<2>(&opened_device_label_),
181 SaveArg<3>(&opened_device)));
182 run_loop.Run();
183 Mock::VerifyAndClearExpectations(&stream_requester_);
184 ASSERT_NE(StreamDeviceInfo::kNoId, opened_device.session_id);
185 opened_session_id_ = opened_device.session_id;
186 }
187 }
188
189 void CloseSession() {
190 if (opened_device_label_.empty())
191 return;
192 media_stream_manager_->CancelRequest(opened_device_label_);
193 opened_device_label_.clear();
194 opened_session_id_ = kInvalidMediaCaptureSessionId;
195 }
196
197 protected:
198 // mojom::VideoCaptureObserver implementation.
199 MOCK_METHOD1(OnStateChanged, void(mojom::VideoCaptureState));
200 void OnBufferCreated(int32_t buffer_id,
201 mojo::ScopedSharedBufferHandle handle) override {
202 DoOnBufferCreated(buffer_id);
203 }
204 MOCK_METHOD1(DoOnBufferCreated, void(int32_t));
205 void OnBufferReady(int32_t buffer_id,
206 mojom::VideoFrameInfoPtr info) override {
207 DoOnBufferReady(buffer_id);
208 }
209 MOCK_METHOD1(DoOnBufferReady, void(int32_t));
210 MOCK_METHOD1(OnBufferDestroyed, void(int32_t));
211
212 void StartCapture() {
213 base::RunLoop run_loop;
214 media::VideoCaptureParams params;
215 params.requested_format = media::VideoCaptureFormat(
216 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
217
218 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED));
219 EXPECT_CALL(*this, DoOnBufferCreated(_))
220 .Times(AnyNumber())
221 .WillRepeatedly(Return());
222 EXPECT_CALL(*this, DoOnBufferReady(_))
223 .Times(AnyNumber())
224 .WillRepeatedly(ExitMessageLoop(task_runner_, run_loop.QuitClosure()));
225
226 host_->Start(kDeviceId, opened_session_id_, params,
227 observer_binding_.CreateInterfacePtrAndBind());
228
229 run_loop.Run();
230 }
231
232 void StartAndImmediateStopCapture() {
233 // Quickly start and then stop capture, without giving much chance for
234 // asynchronous capture operations to produce frames.
235 InSequence s;
236 base::RunLoop run_loop;
237
238 media::VideoCaptureParams params;
239 params.requested_format = media::VideoCaptureFormat(
240 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
241
242 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED));
243 host_->Start(kDeviceId, opened_session_id_, params,
244 observer_binding_.CreateInterfacePtrAndBind());
245
246 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED));
247 host_->Stop(kDeviceId);
248 run_loop.RunUntilIdle();
249 }
250
251 void PauseResumeCapture() {
252 InSequence s;
253 base::RunLoop run_loop;
254
255 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::PAUSED));
256 host_->Pause(kDeviceId);
257
258 media::VideoCaptureParams params;
259 params.requested_format = media::VideoCaptureFormat(
260 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
261
262 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::RESUMED));
263 host_->Resume(kDeviceId, opened_session_id_, params);
264 run_loop.RunUntilIdle();
265 }
266
267 void StopCapture() {
268 base::RunLoop run_loop;
269
270 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED))
271 .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure()));
272 host_->Stop(kDeviceId);
273
274 run_loop.Run();
275
276 EXPECT_TRUE(host_->controllers_.empty());
277 }
278
279 void WaitForOneCapturedBuffer() {
280 base::RunLoop run_loop;
281
282 EXPECT_CALL(*this, DoOnBufferReady(_))
283 .Times(AnyNumber())
284 .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure()))
285 .RetiresOnSaturation();
286 run_loop.Run();
287 }
288
289 void SimulateError() {
290 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::FAILED));
291 VideoCaptureControllerID id(kDeviceId);
292 host_->OnError(id);
293 base::RunLoop().RunUntilIdle();
294 }
295
296 private:
297 // |media_stream_manager_| needs to outlive |thread_bundle_| because it is a
298 // MessageLoop::DestructionObserver.
299 StrictMock<MockMediaStreamRequester> stream_requester_;
300 std::unique_ptr<MediaStreamManager> media_stream_manager_;
301 const content::TestBrowserThreadBundle thread_bundle_;
302 // |audio_manager_| needs to outlive |thread_bundle_| because it uses the
303 // underlying message loop.
304 media::ScopedAudioManagerPtr audio_manager_;
305 content::TestBrowserContext browser_context_;
306 content::TestContentBrowserClient browser_client_;
307 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
308 int opened_session_id_;
309 std::string opened_device_label_;
310
311 std::unique_ptr<VideoCaptureHost> host_;
312 mojo::Binding<mojom::VideoCaptureObserver> observer_binding_;
313
314 DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
315 };
316
317 // Construct and destruct all objects. This is a non trivial sequence.
318 TEST_F(VideoCaptureHostTest, ConstructAndDestruct) {}
319
320 TEST_F(VideoCaptureHostTest, StartAndImmediateStop) {
321 StartAndImmediateStopCapture();
322 }
323
324 TEST_F(VideoCaptureHostTest, StartAndCaptureAndStop) {
325 StartCapture();
326 WaitForOneCapturedBuffer();
327 WaitForOneCapturedBuffer();
328 StopCapture();
329 }
330
331 TEST_F(VideoCaptureHostTest, StartAndErrorAndStop) {
332 StartCapture();
333 SimulateError();
334 StopCapture();
335 }
336
337 TEST_F(VideoCaptureHostTest, StartAndCaptureAndError) {
338 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED))
339 .Times(0);
340 StartCapture();
341 WaitForOneCapturedBuffer();
342 SimulateError();
343 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
344 }
345
346 TEST_F(VideoCaptureHostTest, StartAndPauseAndResumeAndStop) {
347 StartCapture();
348 PauseResumeCapture();
349 StopCapture();
350 }
351
352 TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) {
353 StartCapture();
354
355 // When the session is closed via the stream without stopping capture, the
356 // ENDED event is sent.
357 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::ENDED));
358 CloseSession();
359 base::RunLoop().RunUntilIdle();
360 }
361
362 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698