Index: content/browser/media_stream/video_capture_manager_unittest.cc |
=================================================================== |
--- content/browser/media_stream/video_capture_manager_unittest.cc (revision 0) |
+++ content/browser/media_stream/video_capture_manager_unittest.cc (revision 0) |
@@ -0,0 +1,298 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Unit test for VideoCaptureManager |
+ |
+#include <string> |
+ |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
+#include "base/process_util.h" |
+#include "content/browser/browser_thread.h" |
+#include "content/browser/media_stream/media_stream_provider.h" |
+#include "content/browser/media_stream/video_capture_manager.h" |
+#include "media/video/capture/video_capture_device.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using ::testing::_; |
+using ::testing::AnyNumber; |
+using ::testing::InSequence; |
+using ::testing::Return; |
+ |
+namespace media_stream { |
+ |
+// Listener class used to track progress of VideoCaptureManager test |
+class MockMediaStreamProviderListener : public MediaStreamProviderListener { |
+ public: |
+ MockMediaStreamProviderListener() |
+ : devices_() { |
+ } |
+ ~MockMediaStreamProviderListener() {} |
+ |
+ MOCK_METHOD2(Opened, void(MediaStreamType, MediaCaptureSessionId)); |
+ MOCK_METHOD2(Closed, void(MediaStreamType, MediaCaptureSessionId)); |
+ MOCK_METHOD1(DevicesEnumerated, void(const MediaCaptureDevices&)); |
+ MOCK_METHOD3(Error, void(MediaStreamType, MediaCaptureSessionId, |
+ MediaStreamProviderError)); |
+ |
+ virtual void DevicesEnumerated(MediaStreamType stream_type, |
+ const MediaCaptureDevices& devices) { |
+ devices_.clear(); |
+ for (MediaCaptureDevices::const_iterator it = devices.begin(); |
+ it != devices.end(); |
+ ++it) { |
+ devices_.push_back(*it); |
+ } |
+ DevicesEnumerated(devices); |
+ } |
+ |
+ media_stream::MediaCaptureDevices devices_; |
+}; // class MockMediaStreamProviderListener |
+ |
+} // namespace media_stream |
+ |
+namespace { |
+ |
+// Needed as an input argument to Start() |
+class MockFrameObserver: public media::VideoCaptureDevice::EventHandler { |
+ public: |
+ virtual void OnError() {} |
+ |
+ void OnFrameInfo(const media::VideoCaptureDevice::Capability& info) {} |
+ |
+ virtual void OnIncomingCapturedFrame(const uint8* data, int length, |
+ base::Time timestamp) {} |
+}; |
+ |
+// Test class |
+class VideoCaptureManagerTest : public testing::Test { |
+ public: |
+ VideoCaptureManagerTest() |
+ : listener_(), |
+ message_loop_(), |
+ io_thread_(), |
+ frame_observer_() { |
+ } |
+ virtual ~VideoCaptureManagerTest() {} |
+ |
+ protected: |
+ virtual void SetUp() { |
+ listener_.reset(new media_stream::MockMediaStreamProviderListener()); |
+ message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); |
+ io_thread_.reset(new BrowserThread(BrowserThread::IO, message_loop_.get())); |
+ frame_observer_.reset(new MockFrameObserver()); |
+ } |
+ |
+ virtual void TearDown() { |
+ io_thread_.reset(); |
+ } |
+ |
+ // Called on the VideoCaptureManager thread. |
+ static void PostQuitMessageLoop(MessageLoop* message_loop) { |
+ message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+ } |
+ |
+ // Called on the main thread. |
+ static void PostQuitOnVideoCaptureManagerThread(MessageLoop* message_loop) { |
+ media_stream::VideoCaptureManager::Get()->GetMessageLoop()->PostTask( |
+ FROM_HERE, NewRunnableFunction(&PostQuitMessageLoop, message_loop)); |
+ } |
+ |
+ // SyncWithVideoCaptureManagerThread() waits until all pending tasks on the |
+ // video_capture_manager internal thread are executed while also processing |
+ // pending task in message_loop_ on the current thread. It is used to |
+ // synchronize with the video capture manager thread when we are stopping a |
+ // video capture device. |
+ void SyncWithVideoCaptureManagerThread() { |
+ message_loop_->PostTask( |
+ FROM_HERE, NewRunnableFunction(&PostQuitOnVideoCaptureManagerThread, |
+ message_loop_.get())); |
+ message_loop_->Run(); |
+ } |
+ scoped_ptr<media_stream::MockMediaStreamProviderListener> listener_; |
+ scoped_ptr<MessageLoop> message_loop_; |
+ scoped_ptr<BrowserThread> io_thread_; |
+ scoped_ptr<MockFrameObserver> frame_observer_; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest); |
+}; |
+ |
+// Test cases |
+ |
+// Try to open, start, stop and close a device. |
+TEST_F(VideoCaptureManagerTest, CreateAndClose) { |
+ InSequence s; |
+ EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
+ .Times(1); |
+ |
+ media_stream::VideoCaptureManager* vcm = |
+ media_stream::VideoCaptureManager::Get(); |
+ // Make sure fake devices are used |
+ vcm->UseFakeDevice(); |
+ vcm->Register(listener_.get()); |
+ vcm->EnumerateDevices(); |
+ |
+ // Wait to get device callback... |
+ SyncWithVideoCaptureManagerThread(); |
+ |
+ int video_session_id = vcm->Open(listener_->devices_.front()); |
+ |
+ media::VideoCaptureParams capture_params; |
+ capture_params.session_id = video_session_id; |
+ capture_params.width = 320; |
+ capture_params.height = 240; |
+ capture_params.frame_per_second = 30; |
+ vcm->Start(capture_params, frame_observer_.get()); |
+ |
+ vcm->Stop(video_session_id, NULL); |
+ vcm->Close(video_session_id); |
+ |
+ // Wait to check callbacks before removing the listener |
+ SyncWithVideoCaptureManagerThread(); |
+ vcm->Unregister(); |
+} |
+ |
+// Open the same device twice, should fail. |
+TEST_F(VideoCaptureManagerTest, OpenTwice) { |
+ InSequence s; |
+ EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Error(media_stream::kVideoCapture, _, |
+ media_stream::kDeviceAlreadyInUse)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
+ .Times(1); |
+ |
+ media_stream::VideoCaptureManager* vcm = |
+ media_stream::VideoCaptureManager::Get(); |
+ // Make sure fake devices are used |
+ vcm->UseFakeDevice(); |
+ vcm->Register(listener_.get()); |
+ vcm->EnumerateDevices(); |
+ |
+ // Wait to get device callback... |
+ SyncWithVideoCaptureManagerThread(); |
+ |
+ int video_session_id = vcm->Open(listener_->devices_.front()); |
+ |
+ // This should trigger an error callback with error code 'kDeviceAlreadyInUse' |
+ vcm->Open(listener_->devices_.front()); |
+ |
+ vcm->Close(video_session_id); |
+ |
+ // Wait to check callbacks before removing the listener |
+ SyncWithVideoCaptureManagerThread(); |
+ vcm->Unregister(); |
+} |
+ |
+// Open two different devices. |
+TEST_F(VideoCaptureManagerTest, OpenTwo) { |
+ InSequence s; |
+ EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
+ .Times(2); |
+ EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
+ .Times(2); |
+ |
+ media_stream::VideoCaptureManager* vcm = |
+ media_stream::VideoCaptureManager::Get(); |
+ // Make sure fake devices are used |
+ vcm->UseFakeDevice(); |
+ vcm->Register(listener_.get()); |
+ vcm->EnumerateDevices(); |
+ |
+ // Wait to get device callback... |
+ SyncWithVideoCaptureManagerThread(); |
+ |
+ media_stream::MediaCaptureDevices::iterator it = |
+ listener_->devices_.begin(); |
+ |
+ int video_session_id_first = vcm->Open(*it); |
+ |
+ // This should trigger an error callback with error code 'kDeviceAlreadyInUse' |
+ ++it; |
+ int video_session_id_second = vcm->Open(*it); |
+ |
+ vcm->Close(video_session_id_first); |
+ vcm->Close(video_session_id_second); |
+ |
+ // Wait to check callbacks before removing the listener |
+ SyncWithVideoCaptureManagerThread(); |
+ vcm->Unregister(); |
+} |
+ |
+// Try open a non-existing device. |
+TEST_F(VideoCaptureManagerTest, OpenNotExisting) { |
+ InSequence s; |
+ EXPECT_CALL(*listener_, DevicesEnumerated(_)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Error(media_stream::kVideoCapture, _, |
+ media_stream::kDeviceNotAvailable)) |
+ .Times(1); |
+ |
+ media_stream::VideoCaptureManager* vcm = |
+ media_stream::VideoCaptureManager::Get(); |
+ // Make sure fake devices are used |
+ vcm->UseFakeDevice(); |
+ vcm->Register(listener_.get()); |
+ vcm->EnumerateDevices(); |
+ |
+ // Wait to get device callback... |
+ SyncWithVideoCaptureManagerThread(); |
+ |
+ media_stream::MediaStreamType stream_type = media_stream::kVideoCapture; |
+ std::string device_name("device_doesnt_exist"); |
+ std::string device_id("id_doesnt_exist"); |
+ media_stream::MediaCaptureDeviceInfo dummy_device(stream_type, device_name, |
+ device_id, false); |
+ |
+ // This should fail with error code 'kDeviceNotAvailable' |
+ vcm->Open(dummy_device); |
+ |
+ // Wait to check callbacks before removing the listener |
+ SyncWithVideoCaptureManagerThread(); |
+ vcm->Unregister(); |
+} |
+ |
+// Start a device using "magic" id, i.e. call Start without calling Open. |
+TEST_F(VideoCaptureManagerTest, StartUsingId) { |
+ InSequence s; |
+ EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) |
+ .Times(1); |
+ EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) |
+ .Times(1); |
+ |
+ media_stream::VideoCaptureManager* vcm = |
+ media_stream::VideoCaptureManager::Get(); |
+ // Make sure fake devices are used |
+ vcm->UseFakeDevice(); |
+ vcm->Register(listener_.get()); |
+ |
+ media::VideoCaptureParams capture_params; |
+ capture_params.session_id = |
+ media_stream::VideoCaptureManager::kStartOpenSessionId; |
+ capture_params.width = 320; |
+ capture_params.height = 240; |
+ capture_params.frame_per_second = 30; |
+ // Start shall trigger the Open callback |
+ vcm->Start(capture_params, frame_observer_.get()); |
+ |
+ // Stop shall trigger the Close callback |
+ vcm->Stop(media_stream::VideoCaptureManager::kStartOpenSessionId, NULL); |
+ |
+ // Wait to check callbacks before removing the listener |
+ SyncWithVideoCaptureManagerThread(); |
+ vcm->Unregister(); |
+} |
+ |
+} // namespace |