blob: 89a7a78bd0d09ebc2c1a33ae8b20bfcdbc39dd24 [file] [log] [blame]
// Copyright 2017 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.
#include "base/bind.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "base/timer/timer.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/video_capture/public/cpp/mock_video_frame_handler.h"
#include "services/video_capture/public/mojom/constants.mojom.h"
#include "services/video_capture/public/mojom/device.mojom.h"
#include "services/video_capture/public/mojom/video_capture_service.mojom.h"
#include "services/video_capture/public/mojom/video_frame_handler.mojom.h"
#include "services/video_capture/public/mojom/video_source_provider.mojom.h"
#include "services/video_capture/video_capture_service_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace video_capture {
using testing::_;
using testing::Exactly;
using testing::Invoke;
using testing::InvokeWithoutArgs;
// Test fixture that creates a video_capture::ServiceImpl and sets up a
// local service_manager::Connector through which client code can connect to
// it.
class VideoCaptureServiceLifecycleTest : public ::testing::Test {
public:
VideoCaptureServiceLifecycleTest() = default;
~VideoCaptureServiceLifecycleTest() override = default;
void SetUp() override {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
service_impl_ = std::make_unique<VideoCaptureServiceImpl>(
service_remote_.BindNewPipeAndPassReceiver(),
task_environment_.GetMainThreadTaskRunner());
service_remote_.set_idle_handler(
base::TimeDelta(),
base::BindRepeating(&VideoCaptureServiceLifecycleTest::OnServiceIdle,
base::Unretained(this)));
}
protected:
base::test::TaskEnvironment task_environment_;
std::unique_ptr<VideoCaptureServiceImpl> service_impl_;
mojo::Remote<mojom::VideoCaptureService> service_remote_;
base::MockCallback<mojom::DeviceFactory::GetDeviceInfosCallback>
device_info_receiver_;
base::RunLoop service_idle_wait_loop_;
private:
void OnServiceIdle() { service_idle_wait_loop_.Quit(); }
DISALLOW_COPY_AND_ASSIGN(VideoCaptureServiceLifecycleTest);
};
// Tests that the service quits when the only client disconnects after not
// having done anything other than obtaining a connection to the device factory.
TEST_F(VideoCaptureServiceLifecycleTest,
ServiceQuitsWhenSingleDeviceFactoryClientDisconnected) {
mojo::Remote<mojom::DeviceFactory> factory;
service_remote_->ConnectToDeviceFactory(factory.BindNewPipeAndPassReceiver());
factory.reset();
service_idle_wait_loop_.Run();
}
// Tests that the service quits when the only client disconnects after not
// having done anything other than obtaining a connection to the video source
// provider.
TEST_F(VideoCaptureServiceLifecycleTest,
ServiceQuitsWhenSingleVideoSourceProviderClientDisconnected) {
mojo::Remote<mojom::VideoSourceProvider> source_provider;
service_remote_->ConnectToVideoSourceProvider(
source_provider.BindNewPipeAndPassReceiver());
source_provider.reset();
service_idle_wait_loop_.Run();
}
// Tests that the service quits when the only client disconnects after
// enumerating devices via the video source provider.
TEST_F(VideoCaptureServiceLifecycleTest, ServiceQuitsAfterEnumeratingDevices) {
mojo::Remote<mojom::VideoSourceProvider> source_provider;
service_remote_->ConnectToVideoSourceProvider(
source_provider.BindNewPipeAndPassReceiver());
base::RunLoop wait_loop;
EXPECT_CALL(device_info_receiver_, Run(_))
.WillOnce(
Invoke([&wait_loop](
const std::vector<media::VideoCaptureDeviceInfo>& infos) {
wait_loop.Quit();
}));
source_provider->GetSourceInfos(device_info_receiver_.Get());
wait_loop.Run();
source_provider.reset();
service_idle_wait_loop_.Run();
}
// Tests that enumerating devices works after the only client disconnects and
// reconnects via the video source provider.
TEST_F(VideoCaptureServiceLifecycleTest, EnumerateDevicesAfterReconnect) {
// Connect |source_provider|.
mojo::Remote<mojom::VideoSourceProvider> source_provider;
service_remote_->ConnectToVideoSourceProvider(
source_provider.BindNewPipeAndPassReceiver());
// Disconnect |source_provider| and wait for the disconnect to propagate to
// the service.
{
base::RunLoop wait_loop;
source_provider->Close(base::BindOnce(
[](base::RunLoop* wait_loop) { wait_loop->Quit(); }, &wait_loop));
wait_loop.Run();
source_provider.reset();
}
// Reconnect |source_provider|.
service_remote_->ConnectToVideoSourceProvider(
source_provider.BindNewPipeAndPassReceiver());
// Enumerate devices.
base::RunLoop wait_loop;
EXPECT_CALL(device_info_receiver_, Run(_))
.WillOnce(
Invoke([&wait_loop](
const std::vector<media::VideoCaptureDeviceInfo>& infos) {
wait_loop.Quit();
}));
source_provider->GetSourceInfos(device_info_receiver_.Get());
wait_loop.Run();
source_provider.reset();
service_idle_wait_loop_.Run();
}
// Tests that the service quits when the last client disconnects while using a
// device.
TEST_F(VideoCaptureServiceLifecycleTest,
ServiceQuitsWhenClientDisconnectsWhileUsingDevice) {
mojo::Remote<mojom::DeviceFactory> factory;
service_remote_->ConnectToDeviceFactory(factory.BindNewPipeAndPassReceiver());
// Connect to and start first device (in this case a fake camera).
media::VideoCaptureDeviceInfo fake_device_info;
{
base::RunLoop wait_loop;
EXPECT_CALL(device_info_receiver_, Run(_))
.WillOnce(Invoke(
[&fake_device_info, &wait_loop](
const std::vector<media::VideoCaptureDeviceInfo>& infos) {
fake_device_info = infos[0];
wait_loop.Quit();
}));
factory->GetDeviceInfos(device_info_receiver_.Get());
wait_loop.Run();
}
mojo::Remote<mojom::Device> fake_device;
factory->CreateDevice(
std::move(fake_device_info.descriptor.device_id),
fake_device.BindNewPipeAndPassReceiver(),
base::BindOnce([](mojom::DeviceAccessResultCode result_code) {
ASSERT_EQ(mojom::DeviceAccessResultCode::SUCCESS, result_code);
}));
media::VideoCaptureParams requestable_settings;
requestable_settings.requested_format = fake_device_info.supported_formats[0];
mojo::PendingRemote<mojom::VideoFrameHandler> handler_remote;
MockVideoFrameHandler mock_video_frame_handler(
handler_remote.InitWithNewPipeAndPassReceiver());
fake_device->Start(requestable_settings, std::move(handler_remote));
{
base::RunLoop wait_loop;
EXPECT_CALL(mock_video_frame_handler, OnStarted()).WillOnce([&wait_loop]() {
wait_loop.Quit();
});
wait_loop.Run();
}
// Disconnect
fake_device.reset();
factory.reset();
service_idle_wait_loop_.Run();
}
} // namespace video_capture