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