blob: 5eca54b68a2206221082db48900a370c4620bab6 [file] [log] [blame]
// Copyright 2019 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 "power_manager/powerd/system/wakeup_source_identifier.h"
#include <memory>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_util.h>
#include <base/strings/string_number_conversions.h>
#include <gtest/gtest.h>
#include "power_manager/common/power_constants.h"
#include "power_manager/common/util.h"
#include "power_manager/powerd/system/udev_stub.h"
namespace power_manager {
namespace system {
namespace {
const char kRandomEventCountPath[] = "wakeup/wakeup45/event_count";
const char kTestSysPath[] = "sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/";
// Creates |file_path|. Also creates all necessary parent directories.
void CreateFile(const base::FilePath& file_path) {
ASSERT_TRUE(base::CreateDirectory(file_path.DirName()));
CHECK_EQ(base::WriteFile(file_path, "", 0), 0);
}
void CreatePowerWakeupAttrInDir(const base::FilePath& dir_path) {
const base::FilePath wakeup_path = dir_path.Append(kPowerWakeup);
CreateFile(wakeup_path);
}
void CreateEventCountAttrInSys(const base::FilePath& dir_path) {
const base::FilePath event_count_path =
dir_path.Append(kRandomEventCountPath);
CreateFile(event_count_path);
// By default set the event count to 0
ASSERT_TRUE(util::WriteInt64File(event_count_path, 0));
}
void IncrementEventCount(const base::FilePath& dir_path) {
const base::FilePath event_count_path =
dir_path.Append(kRandomEventCountPath);
std::string event_count_str;
ASSERT_TRUE(base::ReadFileToString(event_count_path, &event_count_str));
base::TrimWhitespaceASCII(event_count_str, base::TRIM_TRAILING,
&event_count_str);
int64_t current_count;
ASSERT_TRUE(base::StringToInt64(event_count_str, &current_count));
ASSERT_TRUE(util::WriteInt64File(event_count_path, current_count + 1));
}
class WakeupSourceIdentifierTest : public ::testing::Test {
public:
WakeupSourceIdentifierTest() {
CHECK(temp_dir_.CreateUniqueTempDir());
wakeup_device_path_ = temp_dir_.GetPath().Append(kTestSysPath);
CreatePowerWakeupAttrInDir(wakeup_device_path_);
CreateEventCountAttrInSys(wakeup_device_path_);
wakeup_source_identifier_ =
std::make_unique<system::WakeupSourceIdentifier>(&udev_);
}
protected:
void SendInputUdevEvent(const UdevEvent::Action action,
const std::string& input_name,
const base::FilePath& wakeup_path) {
UdevDeviceInfo input_device_info;
input_device_info.subsystem = kInputUdevSubsystem;
input_device_info.sysname = input_name;
input_device_info.wakeup_device_path = wakeup_path;
UdevEvent event;
event.action = action;
event.device_info = input_device_info;
udev_.NotifySubsystemObservers(event);
}
UdevStub udev_;
std::unique_ptr<WakeupSourceIdentifier> wakeup_source_identifier_;
base::ScopedTempDir temp_dir_;
base::FilePath wakeup_device_path_;
};
TEST_F(WakeupSourceIdentifierTest, TestWakeDueToInputDevice) {
// Add first input with |wakeup_device_path_|
SendInputUdevEvent(UdevEvent::Action::ADD, "input1", wakeup_device_path_);
// Now let us suspend and increment the event count.
wakeup_source_identifier_->PrepareForSuspendRequest();
IncrementEventCount(wakeup_device_path_);
wakeup_source_identifier_->HandleResume();
EXPECT_TRUE(wakeup_source_identifier_->InputDeviceCausedLastWake());
}
TEST_F(WakeupSourceIdentifierTest, TestAddAndRemoveInputDevice) {
// Add first input with |wakeup_device_path_|
SendInputUdevEvent(UdevEvent::Action::ADD, "input1", wakeup_device_path_);
SendInputUdevEvent(UdevEvent::Action::REMOVE, "input1", wakeup_device_path_);
// Now let us suspend and increment the event count.
wakeup_source_identifier_->PrepareForSuspendRequest();
IncrementEventCount(wakeup_device_path_);
wakeup_source_identifier_->HandleResume();
EXPECT_FALSE(wakeup_source_identifier_->InputDeviceCausedLastWake());
}
TEST_F(WakeupSourceIdentifierTest, TestMultipleInputDevicesWithSameWakePath) {
// Add first input with |wakeup_device_path_|
SendInputUdevEvent(UdevEvent::Action::ADD, "input1", wakeup_device_path_);
SendInputUdevEvent(UdevEvent::Action::ADD, "input2", wakeup_device_path_);
SendInputUdevEvent(UdevEvent::Action::REMOVE, "input1", wakeup_device_path_);
// Now let us suspend and increment the event count.
wakeup_source_identifier_->PrepareForSuspendRequest();
IncrementEventCount(wakeup_device_path_);
wakeup_source_identifier_->HandleResume();
EXPECT_TRUE(wakeup_source_identifier_->InputDeviceCausedLastWake());
}
} // namespace
} // namespace system
} // namespace power_manager