blob: 728001da56f545e4179e8eb24ea71fd0a597ab9b [file] [log] [blame]
// Copyright 2021 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 <utility>
#include <base/test/task_environment.h>
#include <brillo/dbus/dbus_object_test_helpers.h>
#include <brillo/message_loops/base_message_loop.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <dbus/mock_object_proxy.h>
#include <gmock/gmock.h>
#include <hps/daemon/dbus_adaptor.h>
#include <hps/hps.h>
using brillo::dbus_utils::AsyncEventSequencer;
using testing::_;
using testing::InSequence;
using testing::NiceMock;
using testing::Return;
using testing::StrictMock;
namespace hps {
class MockHps : public HPS {
public:
MOCK_METHOD(void,
Init,
(uint32_t, const base::FilePath&, const base::FilePath&),
(override));
MOCK_METHOD(bool, Boot, (), (override));
MOCK_METHOD(void, SkipBoot, (), (override));
MOCK_METHOD(bool, Enable, (uint8_t), (override));
MOCK_METHOD(bool, Disable, (uint8_t), (override));
MOCK_METHOD(int, Result, (int), (override));
MOCK_METHOD(DevInterface*, Device, (), (override));
MOCK_METHOD(bool, Download, (HpsBank, const base::FilePath&), (override));
};
class HpsDaemonTest : public testing::Test {
public:
HpsDaemonTest() {
dbus::Bus::Options options;
mock_bus_ = base::MakeRefCounted<NiceMock<dbus::MockBus>>(options);
dbus::ObjectPath path(::hps::kHpsServicePath);
mock_object_proxy_ = base::MakeRefCounted<NiceMock<dbus::MockObjectProxy>>(
mock_bus_.get(), kHpsServicePath, path);
mock_exported_object_ =
base::MakeRefCounted<NiceMock<dbus::MockExportedObject>>(
mock_bus_.get(), path);
ON_CALL(*mock_bus_, GetExportedObject(path))
.WillByDefault(Return(mock_exported_object_.get()));
ON_CALL(*mock_bus_, GetDBusTaskRunner())
.WillByDefault(
Return(task_environment_.GetMainThreadTaskRunner().get()));
EXPECT_CALL(*mock_exported_object_, ExportMethod(_, _, _, _))
.Times(testing::AnyNumber());
auto hps = std::make_unique<StrictMock<MockHps>>();
mock_hps_ = hps.get();
hps_daemon_.reset(new DBusAdaptor(mock_bus_, std::move(hps), kPollTimeMs));
brillo_loop_.SetAsCurrent();
}
protected:
bool CallEnableFeature(brillo::ErrorPtr* error_ptr, uint8_t feature) {
return hps_daemon_->EnableFeature(error_ptr, feature);
}
bool CallDisableFeature(brillo::ErrorPtr* error_ptr, uint8_t feature) {
return hps_daemon_->DisableFeature(error_ptr, feature);
}
bool CallGetFeatureResult(brillo::ErrorPtr* error_ptr,
uint8_t feature,
uint16_t* result) {
return hps_daemon_->GetFeatureResult(error_ptr, feature, result);
}
base::test::SingleThreadTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
brillo::BaseMessageLoop brillo_loop_{
task_environment_.GetMainThreadTaskRunner().get()};
scoped_refptr<dbus::MockBus> mock_bus_;
scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_;
scoped_refptr<dbus::MockExportedObject> mock_exported_object_;
StrictMock<MockHps>* mock_hps_;
std::unique_ptr<DBusAdaptor> hps_daemon_;
static constexpr uint32_t kPollTimeMs = 500;
};
TEST_F(HpsDaemonTest, EnableFeatureNotReady) {
EXPECT_CALL(*mock_hps_, Enable(0)).WillOnce(Return(false));
brillo::ErrorPtr error;
bool result = CallEnableFeature(&error, 0);
EXPECT_FALSE(result);
EXPECT_EQ("hpsd: Unable to enable feature", error->GetMessage());
}
TEST_F(HpsDaemonTest, EnableFeatureReady) {
EXPECT_CALL(*mock_hps_, Enable(0)).WillOnce(Return(true));
brillo::ErrorPtr error;
bool result = CallEnableFeature(&error, 0);
EXPECT_TRUE(result);
}
TEST_F(HpsDaemonTest, DisableFeatureNotReady) {
EXPECT_CALL(*mock_hps_, Disable(0)).WillOnce(Return(false));
brillo::ErrorPtr error;
bool result = CallDisableFeature(&error, 0);
EXPECT_FALSE(result);
EXPECT_EQ("hpsd: Unable to disable feature", error->GetMessage());
}
TEST_F(HpsDaemonTest, DisableFeatureReady) {
EXPECT_CALL(*mock_hps_, Disable(0)).WillOnce(Return(true));
brillo::ErrorPtr error;
bool result = CallDisableFeature(&error, 0);
EXPECT_TRUE(result);
}
TEST_F(HpsDaemonTest, GetFeatureResultNotReady) {
brillo::ErrorPtr error;
uint16_t result;
EXPECT_CALL(*mock_hps_, Result(0)).WillOnce(Return(-1));
bool call_result = CallGetFeatureResult(&error, 0, &result);
EXPECT_FALSE(call_result);
EXPECT_EQ("hpsd: Feature result not available", error->GetMessage());
}
TEST_F(HpsDaemonTest, GetFeatureResultReady) {
brillo::ErrorPtr error;
uint16_t result;
uint16_t expected_result = RFeat::kValid;
EXPECT_CALL(*mock_hps_, Result(0)).WillOnce(Return(expected_result));
bool call_result = CallGetFeatureResult(&error, 0, &result);
EXPECT_TRUE(call_result);
EXPECT_EQ(expected_result, result);
}
TEST_F(HpsDaemonTest, TestPollTimer) {
{
InSequence sequence;
EXPECT_CALL(*mock_hps_, Enable(0)).WillOnce(Return(true));
EXPECT_CALL(*mock_hps_, Result(0))
.Times(2)
.WillRepeatedly(Return(RFeat::kValid));
EXPECT_CALL(*mock_hps_, Disable(0)).WillOnce(Return(true));
EXPECT_CALL(*mock_hps_, Result(0)).Times(0);
}
brillo::ErrorPtr error;
bool result = CallEnableFeature(&error, 0);
EXPECT_TRUE(result);
// Advance timer far enough so that the poll timer should fire twice.
task_environment_.FastForwardBy(
base::TimeDelta::FromMilliseconds(kPollTimeMs * 2));
// Disable the feature, time should no longer fire.
result = CallDisableFeature(&error, 0);
EXPECT_TRUE(result);
// Poll task should no longer fire if we advance the timer.
task_environment_.FastForwardBy(
base::TimeDelta::FromMilliseconds(kPollTimeMs * 2));
}
TEST_F(HpsDaemonTest, TestPollTimerMultipleFeatures) {
{
InSequence sequence;
EXPECT_CALL(*mock_hps_, Enable(0)).WillOnce(Return(true));
EXPECT_CALL(*mock_hps_, Enable(1)).WillOnce(Return(true));
EXPECT_CALL(*mock_hps_, Result(0)).WillOnce(Return(RFeat::kValid));
EXPECT_CALL(*mock_hps_, Result(1)).WillOnce(Return(RFeat::kValid));
EXPECT_CALL(*mock_hps_, Disable(0)).WillOnce(Return(true));
EXPECT_CALL(*mock_hps_, Result(0)).Times(0);
EXPECT_CALL(*mock_hps_, Result(1)).WillOnce(Return(RFeat::kValid));
EXPECT_CALL(*mock_hps_, Disable(1)).WillOnce(Return(true));
EXPECT_CALL(*mock_hps_, Result(1)).Times(0);
}
brillo::ErrorPtr error;
// Enable features 0 & 1
bool result = CallEnableFeature(&error, 0);
EXPECT_TRUE(result);
result = CallEnableFeature(&error, 1);
EXPECT_TRUE(result);
// Advance timer far enough so that the poll timer should fire.
task_environment_.FastForwardBy(
base::TimeDelta::FromMilliseconds(kPollTimeMs));
// Disable the feature, timer should no longer fire for feature 0.
result = CallDisableFeature(&error, 0);
EXPECT_TRUE(result);
// Advance timer far enough so that the poll timer should fire.
task_environment_.FastForwardBy(
base::TimeDelta::FromMilliseconds(kPollTimeMs));
// Disable the feature, timer should no longer fire for feature 1.
result = CallDisableFeature(&error, 1);
EXPECT_TRUE(result);
// Advance time to ensure no more features are firing.
task_environment_.FastForwardBy(
base::TimeDelta::FromMilliseconds(kPollTimeMs));
}
} // namespace hps