1// Copyright 2014 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 "base/bind.h" 6#include "base/callback.h" 7#include "base/memory/ref_counted.h" 8#include "base/message_loop/message_loop.h" 9#include "base/run_loop.h" 10#include "content/child/child_process.h" 11#include "content/renderer/media/video_capture_impl.h" 12#include "content/renderer/media/video_capture_impl_manager.h" 13#include "content/renderer/media/video_capture_message_filter.h" 14#include "media/base/bind_to_current_loop.h" 15#include "testing/gmock/include/gmock/gmock.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18using ::testing::_; 19using ::testing::DoAll; 20using ::testing::SaveArg; 21using media::BindToCurrentLoop; 22 23namespace content { 24 25ACTION_P(RunClosure, closure) { 26 closure.Run(); 27} 28 29class MockVideoCaptureImpl : public VideoCaptureImpl { 30 public: 31 MockVideoCaptureImpl(media::VideoCaptureSessionId session_id, 32 VideoCaptureMessageFilter* filter, 33 base::Closure destruct_callback) 34 : VideoCaptureImpl(session_id, filter), 35 destruct_callback_(destruct_callback) { 36 } 37 38 virtual ~MockVideoCaptureImpl() { 39 destruct_callback_.Run(); 40 } 41 42 private: 43 base::Closure destruct_callback_; 44 45 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImpl); 46}; 47 48class MockVideoCaptureImplManager : public VideoCaptureImplManager { 49 public: 50 explicit MockVideoCaptureImplManager( 51 base::Closure destruct_video_capture_callback) 52 : destruct_video_capture_callback_( 53 destruct_video_capture_callback) {} 54 virtual ~MockVideoCaptureImplManager() {} 55 56 protected: 57 virtual VideoCaptureImpl* CreateVideoCaptureImplForTesting( 58 media::VideoCaptureSessionId id, 59 VideoCaptureMessageFilter* filter) const OVERRIDE { 60 return new MockVideoCaptureImpl(id, 61 filter, 62 destruct_video_capture_callback_); 63 } 64 65 private: 66 base::Closure destruct_video_capture_callback_; 67 68 DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImplManager); 69}; 70 71class VideoCaptureImplManagerTest : public ::testing::Test { 72 public: 73 VideoCaptureImplManagerTest() 74 : manager_(new MockVideoCaptureImplManager( 75 BindToCurrentLoop(cleanup_run_loop_.QuitClosure()))) { 76 params_.requested_format = media::VideoCaptureFormat( 77 gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420); 78 child_process_.reset(new ChildProcess()); 79 } 80 81 void FakeChannelSetup() { 82 scoped_refptr<base::MessageLoopProxy> loop = 83 child_process_->io_message_loop_proxy(); 84 if (!loop->BelongsToCurrentThread()) { 85 loop->PostTask( 86 FROM_HERE, 87 base::Bind( 88 &VideoCaptureImplManagerTest::FakeChannelSetup, 89 base::Unretained(this))); 90 return; 91 } 92 manager_->video_capture_message_filter()->OnFilterAdded(NULL); 93 } 94 95 protected: 96 MOCK_METHOD3(OnFrameReady, 97 void(const scoped_refptr<media::VideoFrame>&, 98 const media::VideoCaptureFormat&, 99 const base::TimeTicks& estimated_capture_time)); 100 MOCK_METHOD0(OnStarted, void()); 101 MOCK_METHOD0(OnStopped, void()); 102 103 void OnStateUpdate(VideoCaptureState state) { 104 switch (state) { 105 case VIDEO_CAPTURE_STATE_STARTED: 106 OnStarted(); 107 break; 108 case VIDEO_CAPTURE_STATE_STOPPED: 109 OnStopped(); 110 break; 111 default: 112 NOTREACHED(); 113 } 114 } 115 116 base::Closure StartCapture(const media::VideoCaptureParams& params) { 117 return manager_->StartCapture( 118 0, params, 119 base::Bind(&VideoCaptureImplManagerTest::OnStateUpdate, 120 base::Unretained(this)), 121 base::Bind(&VideoCaptureImplManagerTest::OnFrameReady, 122 base::Unretained(this))); 123 } 124 125 base::MessageLoop message_loop_; 126 scoped_ptr<ChildProcess> child_process_; 127 media::VideoCaptureParams params_; 128 base::RunLoop cleanup_run_loop_; 129 scoped_ptr<MockVideoCaptureImplManager> manager_; 130 131 private: 132 DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplManagerTest); 133}; 134 135// Multiple clients with the same session id. There is only one 136// media::VideoCapture object. 137TEST_F(VideoCaptureImplManagerTest, MultipleClients) { 138 base::Closure release_cb1 = manager_->UseDevice(0); 139 base::Closure release_cb2 = manager_->UseDevice(0); 140 base::Closure stop_cb1, stop_cb2; 141 { 142 base::RunLoop run_loop; 143 base::Closure quit_closure = BindToCurrentLoop( 144 run_loop.QuitClosure()); 145 EXPECT_CALL(*this, OnStarted()).WillOnce( 146 RunClosure(quit_closure)); 147 EXPECT_CALL(*this, OnStarted()).RetiresOnSaturation(); 148 stop_cb1 = StartCapture(params_); 149 stop_cb2 = StartCapture(params_); 150 FakeChannelSetup(); 151 run_loop.Run(); 152 } 153 154 { 155 base::RunLoop run_loop; 156 base::Closure quit_closure = BindToCurrentLoop( 157 run_loop.QuitClosure()); 158 EXPECT_CALL(*this, OnStopped()).WillOnce( 159 RunClosure(quit_closure)); 160 EXPECT_CALL(*this, OnStopped()).RetiresOnSaturation(); 161 stop_cb1.Run(); 162 stop_cb2.Run(); 163 run_loop.Run(); 164 } 165 166 release_cb1.Run(); 167 release_cb2.Run(); 168 cleanup_run_loop_.Run(); 169} 170 171TEST_F(VideoCaptureImplManagerTest, NoLeak) { 172 manager_->UseDevice(0).Reset(); 173 manager_.reset(); 174 cleanup_run_loop_.Run(); 175} 176 177} // namespace content 178