video_capture_manager_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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// Unit test for VideoCaptureManager.
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/memory/ref_counted.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/message_loop/message_loop.h"
13#include "base/run_loop.h"
14#include "content/browser/browser_thread_impl.h"
15#include "content/browser/renderer_host/media/media_stream_provider.h"
16#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
17#include "content/browser/renderer_host/media/video_capture_manager.h"
18#include "content/common/media/media_stream_options.h"
19#include "media/video/capture/video_capture_device.h"
20#include "testing/gmock/include/gmock/gmock.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23using ::testing::_;
24using ::testing::AnyNumber;
25using ::testing::InSequence;
26using ::testing::Return;
27using ::testing::SaveArg;
28
29namespace content {
30
31// Listener class used to track progress of VideoCaptureManager test.
32class MockMediaStreamProviderListener : public MediaStreamProviderListener {
33 public:
34  MockMediaStreamProviderListener() {}
35  ~MockMediaStreamProviderListener() {}
36
37  MOCK_METHOD2(Opened, void(MediaStreamType, int));
38  MOCK_METHOD2(Closed, void(MediaStreamType, int));
39  MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType,
40                                       const StreamDeviceInfoArray&));
41  MOCK_METHOD3(Error, void(MediaStreamType, int,
42                           MediaStreamProviderError));
43};  // class MockMediaStreamProviderListener
44
45// Needed as an input argument to StartCaptureForClient().
46class MockFrameObserver : public VideoCaptureControllerEventHandler {
47 public:
48  MOCK_METHOD1(OnError, void(const VideoCaptureControllerID& id));
49
50  virtual void OnBufferCreated(const VideoCaptureControllerID& id,
51                               base::SharedMemoryHandle handle,
52                               int length, int buffer_id) OVERRIDE {}
53  virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
54                               int buffer_id) OVERRIDE {}
55  virtual void OnBufferReady(
56      const VideoCaptureControllerID& id,
57      int buffer_id,
58      base::Time timestamp,
59      const media::VideoCaptureFormat& format) OVERRIDE {}
60  virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {}
61
62  void OnGotControllerCallback(VideoCaptureControllerID) {}
63};
64
65// Test class
66class VideoCaptureManagerTest : public testing::Test {
67 public:
68  VideoCaptureManagerTest() : next_client_id_(1) {}
69  virtual ~VideoCaptureManagerTest() {}
70
71 protected:
72  virtual void SetUp() OVERRIDE {
73    listener_.reset(new MockMediaStreamProviderListener());
74    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
75    io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
76                                           message_loop_.get()));
77    vcm_ = new VideoCaptureManager();
78    vcm_->UseFakeDevice();
79    vcm_->Register(listener_.get(), message_loop_->message_loop_proxy().get());
80    frame_observer_.reset(new MockFrameObserver());
81  }
82
83  virtual void TearDown() OVERRIDE {}
84
85  void OnGotControllerCallback(
86      VideoCaptureControllerID id,
87      base::Closure quit_closure,
88      bool expect_success,
89      const base::WeakPtr<VideoCaptureController>& controller) {
90    if (expect_success) {
91      ASSERT_TRUE(controller);
92      ASSERT_TRUE(0 == controllers_.count(id));
93      controllers_[id] = controller.get();
94    } else {
95      ASSERT_TRUE(NULL == controller);
96    }
97    quit_closure.Run();
98  }
99
100  VideoCaptureControllerID StartClient(int session_id, bool expect_success) {
101    media::VideoCaptureParams params;
102    params.requested_format = media::VideoCaptureFormat(
103        gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
104
105    VideoCaptureControllerID client_id(next_client_id_++);
106    base::RunLoop run_loop;
107    vcm_->StartCaptureForClient(
108        session_id,
109        params,
110        base::kNullProcessHandle,
111        client_id,
112        frame_observer_.get(),
113        base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback,
114                   base::Unretained(this),
115                   client_id,
116                   run_loop.QuitClosure(),
117                   expect_success));
118    run_loop.Run();
119    return client_id;
120  }
121
122  void StopClient(VideoCaptureControllerID client_id) {
123    ASSERT_TRUE(1 == controllers_.count(client_id));
124    vcm_->StopCaptureForClient(controllers_[client_id], client_id,
125                               frame_observer_.get());
126    controllers_.erase(client_id);
127  }
128
129  int next_client_id_;
130  std::map<VideoCaptureControllerID, VideoCaptureController*> controllers_;
131  scoped_refptr<VideoCaptureManager> vcm_;
132  scoped_ptr<MockMediaStreamProviderListener> listener_;
133  scoped_ptr<base::MessageLoop> message_loop_;
134  scoped_ptr<BrowserThreadImpl> io_thread_;
135  scoped_ptr<MockFrameObserver> frame_observer_;
136
137 private:
138  DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest);
139};
140
141// Test cases
142
143// Try to open, start, stop and close a device.
144TEST_F(VideoCaptureManagerTest, CreateAndClose) {
145  StreamDeviceInfoArray devices;
146
147  InSequence s;
148  EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
149      .Times(1).WillOnce(SaveArg<1>(&devices));
150  EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
151  EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
152
153  vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
154
155  // Wait to get device callback.
156  message_loop_->RunUntilIdle();
157
158  int video_session_id = vcm_->Open(devices.front());
159  VideoCaptureControllerID client_id = StartClient(video_session_id, true);
160
161  StopClient(client_id);
162  vcm_->Close(video_session_id);
163
164  // Wait to check callbacks before removing the listener.
165  message_loop_->RunUntilIdle();
166  vcm_->Unregister();
167}
168
169// Open the same device twice.
170TEST_F(VideoCaptureManagerTest, OpenTwice) {
171  StreamDeviceInfoArray devices;
172
173  InSequence s;
174  EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
175      .Times(1).WillOnce(SaveArg<1>(&devices));
176  EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
177  EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
178
179  vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
180
181  // Wait to get device callback.
182  message_loop_->RunUntilIdle();
183
184  int video_session_id_first = vcm_->Open(devices.front());
185
186  // This should trigger an error callback with error code
187  // 'kDeviceAlreadyInUse'.
188  int video_session_id_second = vcm_->Open(devices.front());
189  EXPECT_NE(video_session_id_first, video_session_id_second);
190
191  vcm_->Close(video_session_id_first);
192  vcm_->Close(video_session_id_second);
193
194  // Wait to check callbacks before removing the listener.
195  message_loop_->RunUntilIdle();
196  vcm_->Unregister();
197}
198
199// Open two different devices.
200TEST_F(VideoCaptureManagerTest, OpenTwo) {
201  StreamDeviceInfoArray devices;
202
203  InSequence s;
204  EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
205      .Times(1).WillOnce(SaveArg<1>(&devices));
206  EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
207  EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
208
209  vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
210
211  // Wait to get device callback.
212  message_loop_->RunUntilIdle();
213
214  StreamDeviceInfoArray::iterator it = devices.begin();
215
216  int video_session_id_first = vcm_->Open(*it);
217  ++it;
218  int video_session_id_second = vcm_->Open(*it);
219
220  vcm_->Close(video_session_id_first);
221  vcm_->Close(video_session_id_second);
222
223  // Wait to check callbacks before removing the listener.
224  message_loop_->RunUntilIdle();
225  vcm_->Unregister();
226}
227
228// Try open a non-existing device.
229TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
230  StreamDeviceInfoArray devices;
231
232  InSequence s;
233  EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
234      .Times(1).WillOnce(SaveArg<1>(&devices));
235  EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
236  EXPECT_CALL(*frame_observer_, OnError(_)).Times(1);
237  EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
238
239  vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
240
241  // Wait to get device callback.
242  message_loop_->RunUntilIdle();
243
244  MediaStreamType stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
245  std::string device_name("device_doesnt_exist");
246  std::string device_id("id_doesnt_exist");
247  StreamDeviceInfo dummy_device(stream_type, device_name, device_id);
248
249  // This should fail with an error to the controller.
250  int session_id = vcm_->Open(dummy_device);
251  VideoCaptureControllerID client_id = StartClient(session_id, true);
252  message_loop_->RunUntilIdle();
253
254  StopClient(client_id);
255  vcm_->Close(session_id);
256  message_loop_->RunUntilIdle();
257
258  vcm_->Unregister();
259}
260
261// Start a device without calling Open, using a non-magic ID.
262TEST_F(VideoCaptureManagerTest, StartInvalidSession) {
263  StartClient(22, false);
264
265  // Wait to check callbacks before removing the listener.
266  message_loop_->RunUntilIdle();
267  vcm_->Unregister();
268}
269
270// Open and start a device, close it before calling Stop.
271TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
272  StreamDeviceInfoArray devices;
273
274  InSequence s;
275  EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
276      .Times(1).WillOnce(SaveArg<1>(&devices));
277  EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
278  EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
279
280  vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
281
282  // Wait to get device callback.
283  message_loop_->RunUntilIdle();
284
285  int video_session_id = vcm_->Open(devices.front());
286
287  VideoCaptureControllerID client_id = StartClient(video_session_id, true);
288
289  // Close will stop the running device, an assert will be triggered in
290  // VideoCaptureManager destructor otherwise.
291  vcm_->Close(video_session_id);
292  StopClient(client_id);
293
294  // Wait to check callbacks before removing the listener
295  message_loop_->RunUntilIdle();
296  vcm_->Unregister();
297}
298
299}  // namespace content
300