OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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/memory/scoped_ptr.h" |
| 10 #include "base/message_loop.h" |
| 11 #include "base/process_util.h" |
| 12 #include "content/browser/browser_thread.h" |
| 13 #include "content/browser/media_stream/media_stream_provider.h" |
| 14 #include "content/browser/media_stream/video_capture_manager.h" |
| 15 #include "media/video/capture/video_capture_device.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 using ::testing::_; |
| 20 using ::testing::AnyNumber; |
| 21 using ::testing::InSequence; |
| 22 using ::testing::Return; |
| 23 |
| 24 namespace media_stream { |
| 25 |
| 26 // Listener class used to track progress of VideoCaptureManager test |
| 27 class MockMediaStreamProviderListener : public MediaStreamProviderListener { |
| 28 public: |
| 29 MockMediaStreamProviderListener() |
| 30 : devices_() { |
| 31 } |
| 32 ~MockMediaStreamProviderListener() {} |
| 33 |
| 34 MOCK_METHOD2(Opened, void(MediaStreamType, MediaCaptureSessionId)); |
| 35 MOCK_METHOD2(Closed, void(MediaStreamType, MediaCaptureSessionId)); |
| 36 MOCK_METHOD1(DevicesEnumerated, void(const MediaCaptureDevices&)); |
| 37 MOCK_METHOD3(Error, void(MediaStreamType, MediaCaptureSessionId, |
| 38 MediaStreamProviderError)); |
| 39 |
| 40 virtual void DevicesEnumerated(MediaStreamType stream_type, |
| 41 const MediaCaptureDevices& devices) { |
| 42 devices_.clear(); |
| 43 for (MediaCaptureDevices::const_iterator it = devices.begin(); |
| 44 it != devices.end(); |
| 45 ++it) { |
| 46 devices_.push_back(*it); |
| 47 } |
| 48 DevicesEnumerated(devices); |
| 49 } |
| 50 |
| 51 media_stream::MediaCaptureDevices devices_; |
| 52 }; // class MockMediaStreamProviderListener |
| 53 |
| 54 } // namespace media_stream |
| 55 |
| 56 namespace { |
| 57 |
| 58 // Needed as an input argument to Start() |
| 59 class MockFrameObserver: public media::VideoCaptureDevice::EventHandler { |
| 60 public: |
| 61 virtual void OnError() {} |
| 62 |
| 63 void OnFrameInfo(const media::VideoCaptureDevice::Capability& info) {} |
| 64 |
| 65 virtual void OnIncomingCapturedFrame(const uint8* data, int length, |
| 66 base::Time timestamp) {} |
| 67 }; |
| 68 |
| 69 // Test class |
| 70 class VideoCaptureManagerTest : public testing::Test { |
| 71 public: |
| 72 VideoCaptureManagerTest() |
| 73 : listener_(), |
| 74 message_loop_(), |
| 75 io_thread_(), |
| 76 frame_observer_() { |
| 77 } |
| 78 virtual ~VideoCaptureManagerTest() {} |
| 79 |
| 80 protected: |
| 81 virtual void SetUp() { |
| 82 listener_.reset(new media_stream::MockMediaStreamProviderListener()); |
| 83 message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); |
| 84 io_thread_.reset(new BrowserThread(BrowserThread::IO, message_loop_.get())); |
| 85 frame_observer_.reset(new MockFrameObserver()); |
| 86 } |
| 87 |
| 88 virtual void TearDown() { |
| 89 io_thread_.reset(); |
| 90 } |
| 91 |
| 92 // Called on the VideoCaptureManager thread. |
| 93 static void PostQuitMessageLoop(MessageLoop* message_loop) { |
| 94 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 95 } |
| 96 |
| 97 // Called on the main thread. |
| 98 static void PostQuitOnVideoCaptureManagerThread(MessageLoop* message_loop) { |
| 99 media_stream::VideoCaptureManager::Get()->GetMessageLoop()->PostTask( |
| 100 FROM_HERE, NewRunnableFunction(&PostQuitMessageLoop, message_loop)); |
| 101 } |
| 102 |
| 103 // SyncWithVideoCaptureManagerThread() waits until all pending tasks on the |
| 104 // video_capture_manager internal thread are executed while also processing |
| 105 // pending task in message_loop_ on the current thread. It is used to |
| 106 // synchronize with the video capture manager thread when we are stopping a |
| 107 // video capture device. |
| 108 void SyncWithVideoCaptureManagerThread() { |
| 109 message_loop_->PostTask( |
| 110 FROM_HERE, NewRunnableFunction(&PostQuitOnVideoCaptureManagerThread, |
| 111 message_loop_.get())); |
| 112 message_loop_->Run(); |
| 113 } |
| 114 scoped_ptr<media_stream::MockMediaStreamProviderListener> listener_; |
| 115 scoped_ptr<MessageLoop> message_loop_; |
| 116 scoped_ptr<BrowserThread> io_thread_; |
| 117 scoped_ptr<MockFrameObserver> frame_observer_; |
| 118 |
| 119 private: |
| 120 DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest); |
| 121 }; |
| 122 |
| 123 // Test cases |
| 124 |
| 125 // Try to open, start, stop and close a device. |
| 126 TEST_F(VideoCaptureManagerTest, CreateAndClose) { |
| 127 InSequence s; |
| 128 EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
| 129 .Times(1); |
| 130 EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
| 131 .Times(1); |
| 132 EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
| 133 .Times(1); |
| 134 |
| 135 media_stream::VideoCaptureManager* vcm = |
| 136 media_stream::VideoCaptureManager::Get(); |
| 137 // Make sure fake devices are used |
| 138 vcm->UseFakeDevice(); |
| 139 vcm->Register(listener_.get()); |
| 140 vcm->EnumerateDevices(); |
| 141 |
| 142 // Wait to get device callback... |
| 143 SyncWithVideoCaptureManagerThread(); |
| 144 |
| 145 int video_session_id = vcm->Open(listener_->devices_.front()); |
| 146 |
| 147 media::VideoCaptureParams capture_params; |
| 148 capture_params.session_id = video_session_id; |
| 149 capture_params.width = 320; |
| 150 capture_params.height = 240; |
| 151 capture_params.frame_per_second = 30; |
| 152 vcm->Start(capture_params, frame_observer_.get()); |
| 153 |
| 154 vcm->Stop(video_session_id, NULL); |
| 155 vcm->Close(video_session_id); |
| 156 |
| 157 // Wait to check callbacks before removing the listener |
| 158 SyncWithVideoCaptureManagerThread(); |
| 159 vcm->Unregister(); |
| 160 } |
| 161 |
| 162 // Open the same device twice, should fail. |
| 163 TEST_F(VideoCaptureManagerTest, OpenTwice) { |
| 164 InSequence s; |
| 165 EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
| 166 .Times(1); |
| 167 EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
| 168 .Times(1); |
| 169 EXPECT_CALL(*listener_, Error(media_stream::kVideoCapture, _, |
| 170 media_stream::kDeviceAlreadyInUse)) |
| 171 .Times(1); |
| 172 EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
| 173 .Times(1); |
| 174 |
| 175 media_stream::VideoCaptureManager* vcm = |
| 176 media_stream::VideoCaptureManager::Get(); |
| 177 // Make sure fake devices are used |
| 178 vcm->UseFakeDevice(); |
| 179 vcm->Register(listener_.get()); |
| 180 vcm->EnumerateDevices(); |
| 181 |
| 182 // Wait to get device callback... |
| 183 SyncWithVideoCaptureManagerThread(); |
| 184 |
| 185 int video_session_id = vcm->Open(listener_->devices_.front()); |
| 186 |
| 187 // This should trigger an error callback with error code 'kDeviceAlreadyInUse' |
| 188 vcm->Open(listener_->devices_.front()); |
| 189 |
| 190 vcm->Close(video_session_id); |
| 191 |
| 192 // Wait to check callbacks before removing the listener |
| 193 SyncWithVideoCaptureManagerThread(); |
| 194 vcm->Unregister(); |
| 195 } |
| 196 |
| 197 // Open two different devices. |
| 198 TEST_F(VideoCaptureManagerTest, OpenTwo) { |
| 199 InSequence s; |
| 200 EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
| 201 .Times(1); |
| 202 EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
| 203 .Times(2); |
| 204 EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
| 205 .Times(2); |
| 206 |
| 207 media_stream::VideoCaptureManager* vcm = |
| 208 media_stream::VideoCaptureManager::Get(); |
| 209 // Make sure fake devices are used |
| 210 vcm->UseFakeDevice(); |
| 211 vcm->Register(listener_.get()); |
| 212 vcm->EnumerateDevices(); |
| 213 |
| 214 // Wait to get device callback... |
| 215 SyncWithVideoCaptureManagerThread(); |
| 216 |
| 217 media_stream::MediaCaptureDevices::iterator it = |
| 218 listener_->devices_.begin(); |
| 219 |
| 220 int video_session_id_first = vcm->Open(*it); |
| 221 |
| 222 // This should trigger an error callback with error code 'kDeviceAlreadyInUse' |
| 223 ++it; |
| 224 int video_session_id_second = vcm->Open(*it); |
| 225 |
| 226 vcm->Close(video_session_id_first); |
| 227 vcm->Close(video_session_id_second); |
| 228 |
| 229 // Wait to check callbacks before removing the listener |
| 230 SyncWithVideoCaptureManagerThread(); |
| 231 vcm->Unregister(); |
| 232 } |
| 233 |
| 234 // Try open a non-existing device. |
| 235 TEST_F(VideoCaptureManagerTest, OpenNotExisting) { |
| 236 InSequence s; |
| 237 EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
| 238 .Times(1); |
| 239 EXPECT_CALL(*listener_, Error(media_stream::kVideoCapture, _, |
| 240 media_stream::kDeviceNotAvailable)) |
| 241 .Times(1); |
| 242 |
| 243 media_stream::VideoCaptureManager* vcm = |
| 244 media_stream::VideoCaptureManager::Get(); |
| 245 // Make sure fake devices are used |
| 246 vcm->UseFakeDevice(); |
| 247 vcm->Register(listener_.get()); |
| 248 vcm->EnumerateDevices(); |
| 249 |
| 250 // Wait to get device callback... |
| 251 SyncWithVideoCaptureManagerThread(); |
| 252 |
| 253 media_stream::MediaStreamType stream_type = media_stream::kVideoCapture; |
| 254 std::string device_name("device_doesnt_exist"); |
| 255 std::string device_id("id_doesnt_exist"); |
| 256 media_stream::MediaCaptureDeviceInfo dummy_device(stream_type, device_name, |
| 257 device_id, false); |
| 258 |
| 259 // This should fail with error code 'kDeviceNotAvailable' |
| 260 vcm->Open(dummy_device); |
| 261 |
| 262 // Wait to check callbacks before removing the listener |
| 263 SyncWithVideoCaptureManagerThread(); |
| 264 vcm->Unregister(); |
| 265 } |
| 266 |
| 267 // Start a device using "magic" id, i.e. call Start without calling Open. |
| 268 TEST_F(VideoCaptureManagerTest, StartUsingId) { |
| 269 InSequence s; |
| 270 EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
| 271 .Times(1); |
| 272 EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
| 273 .Times(1); |
| 274 |
| 275 media_stream::VideoCaptureManager* vcm = |
| 276 media_stream::VideoCaptureManager::Get(); |
| 277 // Make sure fake devices are used |
| 278 vcm->UseFakeDevice(); |
| 279 vcm->Register(listener_.get()); |
| 280 |
| 281 media::VideoCaptureParams capture_params; |
| 282 capture_params.session_id = |
| 283 media_stream::VideoCaptureManager::kStartOpenSessionId; |
| 284 capture_params.width = 320; |
| 285 capture_params.height = 240; |
| 286 capture_params.frame_per_second = 30; |
| 287 // Start shall trigger the Open callback |
| 288 vcm->Start(capture_params, frame_observer_.get()); |
| 289 |
| 290 // Stop shall trigger the Close callback |
| 291 vcm->Stop(media_stream::VideoCaptureManager::kStartOpenSessionId, NULL); |
| 292 |
| 293 // Wait to check callbacks before removing the listener |
| 294 SyncWithVideoCaptureManagerThread(); |
| 295 vcm->Unregister(); |
| 296 } |
| 297 |
| 298 } // namespace |
OLD | NEW |