blob: 9711ded8a0f68aeab2c73c3e6050648a6dd42900 [file] [log] [blame]
// Copyright 2018 The Chromium OS 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 <linux/cec-funcs.h>
#include <memory>
#include <utility>
#include <vector>
#include <base/bind.h>
#include <base/macros.h>
#include <gmock/gmock.h>
#include "cecservice/cec_device_mock.h"
#include "cecservice/cec_fd_mock.h"
#include "cecservice/cec_manager.h"
#include "cecservice/udev_mock.h"
using ::testing::_;
using ::testing::ByMove;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SetArgPointee;
namespace cecservice {
namespace {
void Copy(std::vector<TvPowerStatus>* out,
const std::vector<TvPowerStatus>& in) {
*out = in;
}
} // namespace
class CecManagerTest : public ::testing::Test {
public:
CecManagerTest();
~CecManagerTest() = default;
protected:
CecDeviceFactoryMock cec_factory_mock_;
Udev::DeviceCallback device_added_callback_;
Udev::DeviceCallback device_removed_callback_;
std::unique_ptr<UdevMock> udev_mock_ = std::make_unique<UdevMock>();
NiceMock<UdevFactoryMock> udev_factory_mock_;
private:
DISALLOW_COPY_AND_ASSIGN(CecManagerTest);
};
CecManagerTest::CecManagerTest() {
ON_CALL(udev_factory_mock_, Create(_, _))
.WillByDefault(
Invoke([&](const Udev::DeviceCallback& device_added_callback,
const Udev::DeviceCallback& device_removed_callback) {
device_added_callback_ = device_added_callback;
device_removed_callback_ = device_removed_callback;
return std::move(udev_mock_);
}));
}
TEST_F(CecManagerTest, TestEnumerateAndCreate) {
std::vector<base::FilePath> devices = {base::FilePath("/dev/cec0"),
base::FilePath("/dev/cec1")};
EXPECT_CALL(*udev_mock_, EnumerateDevices(_))
.WillOnce(DoAll(SetArgPointee<0>(devices), Return(true)));
EXPECT_CALL(cec_factory_mock_, Create(base::FilePath("/dev/cec0")))
.WillOnce(Return(ByMove(std::make_unique<CecDeviceMock>())));
EXPECT_CALL(cec_factory_mock_, Create(base::FilePath("/dev/cec1")))
.WillOnce(Return(ByMove(std::make_unique<CecDeviceMock>())));
auto cec_manager =
std::make_unique<CecManager>(udev_factory_mock_, cec_factory_mock_);
}
TEST_F(CecManagerTest, TestAddRemoveDevice) {
EXPECT_CALL(*udev_mock_, EnumerateDevices(_)).WillOnce(Return(true));
auto cec_manager =
std::make_unique<CecManager>(udev_factory_mock_, cec_factory_mock_);
// Test device add.
CecDeviceMock* device_mock = nullptr;
EXPECT_CALL(cec_factory_mock_, Create(base::FilePath("/dev/cec0")))
.WillOnce(Invoke([&](const base::FilePath&) {
auto mock = std::make_unique<CecDeviceMock>();
device_mock = mock.get();
return mock;
}));
device_added_callback_.Run(base::FilePath("/dev/cec0"));
// Test removal.
EXPECT_CALL(*device_mock, DestructorCalled());
// Remove device.
device_removed_callback_.Run(base::FilePath("/dev/cec0"));
// Make sure that the device is now destroyed.
EXPECT_TRUE(Mock::VerifyAndClearExpectations(device_mock));
}
TEST_F(CecManagerTest, TestCommandForwarding) {
std::vector<base::FilePath> devices = {base::FilePath("/dev/cec0")};
EXPECT_CALL(*udev_mock_, EnumerateDevices(_))
.WillOnce(DoAll(SetArgPointee<0>(devices), Return(true)));
CecDeviceMock* device_mock = nullptr;
EXPECT_CALL(cec_factory_mock_, Create(base::FilePath("/dev/cec0")))
.WillOnce(Invoke([&](const base::FilePath&) {
auto mock = std::make_unique<CecDeviceMock>();
device_mock = mock.get();
return mock;
}));
auto cec_manager =
std::make_unique<CecManager>(udev_factory_mock_, cec_factory_mock_);
EXPECT_CALL(*device_mock, SetStandBy());
cec_manager->SetStandBy();
EXPECT_CALL(*device_mock, SetWakeUp());
cec_manager->SetWakeUp();
}
TEST_F(CecManagerTest, TestPowerQuery) {
EXPECT_CALL(*udev_mock_, EnumerateDevices(_))
.WillOnce(DoAll(SetArgPointee<0>(std::vector<base::FilePath>(1)),
Return(true)));
CecDeviceMock* cec_mock = nullptr;
EXPECT_CALL(cec_factory_mock_, Create(_))
.WillOnce(Invoke([&](const base::FilePath&) {
auto mock = std::make_unique<CecDeviceMock>();
cec_mock = mock.get();
return mock;
}));
auto cec_manager =
std::make_unique<CecManager>(udev_factory_mock_, cec_factory_mock_);
CecDevice::GetTvPowerStatusCallback callback;
EXPECT_CALL(*cec_mock, GetTvPowerStatus(_)).WillOnce(::SaveArg<0>(&callback));
std::vector<TvPowerStatus> result;
cec_manager->GetTvsPowerStatus(base::Bind(Copy, &result));
// Respond.
callback.Run(kTvPowerStatusToStandBy);
ASSERT_EQ(1u, result.size());
EXPECT_EQ(kTvPowerStatusToStandBy, result[0]);
}
TEST_F(CecManagerTest, TestDeviceRemovalWhileTvPowerQueryIsOngoing) {
EXPECT_CALL(*udev_mock_, EnumerateDevices(_))
.WillOnce(DoAll(SetArgPointee<0>(std::vector<base::FilePath>{
base::FilePath("/dev/cec0")}),
Return(true)));
EXPECT_CALL(cec_factory_mock_, Create(_))
.WillOnce(Return(ByMove(std::make_unique<NiceMock<CecDeviceMock>>())));
auto cec_manager =
std::make_unique<CecManager>(udev_factory_mock_, cec_factory_mock_);
// We expect to get a vector of length 0 in response, in order to check for
// that, set initial vector's length to 1.
std::vector<TvPowerStatus> result(1);
cec_manager->GetTvsPowerStatus(base::Bind(Copy, &result));
// Remove the device.
device_removed_callback_.Run(base::FilePath("/dev/cec0"));
// We should get an empty answer.
EXPECT_EQ(0u, result.size());
}
} // namespace cecservice