blob: 9ad3ec2680a4a6388f0c657cccbf1d1c0b2998da [file] [log] [blame]
// Copyright (c) 2011 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 "cros-disks/udev_device.h"
#include <libudev.h>
#include <base/logging.h>
#include <gtest/gtest.h>
#include <linux/limits.h>
#include <rootdev/rootdev.h>
using std::string;
using std::vector;
namespace {
const char kLoopDevicePrefix[] = "/dev/loop";
const char kRamDeviceFile[] = "/dev/ram0";
const char kZRamDeviceFile[] = "/dev/zram0";
} // namespace
namespace cros_disks {
class UdevDeviceTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
udev_ = udev_new();
if (!udev_)
return;
string boot_device_path = GetBootDevicePath();
udev_enumerate* enumerate = udev_enumerate_new(udev_);
udev_enumerate_add_match_subsystem(enumerate, "block");
udev_enumerate_scan_devices(enumerate);
udev_list_entry *device_list, *device_list_entry;
device_list = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(device_list_entry, device_list) {
const char* path = udev_list_entry_get_name(device_list_entry);
udev_device* device = udev_device_new_from_syspath(udev_, path);
if (!device)
continue;
const char* device_file = udev_device_get_devnode(device);
if (!device_file)
continue;
if (!boot_device_ && !boot_device_path.empty() &&
boot_device_path == device_file) {
udev_device_ref(device);
boot_device_ = device;
// Check if the boot device is also mounted. If so, use it for tests
// that expect a mounted device since the boot device is unlikely to
// be unmounted during the tests.
vector<string> mount_paths = UdevDevice::GetMountPaths(device_file);
if (!mounted_device_ && !mount_paths.empty()) {
udev_device_ref(device);
mounted_device_ = device;
}
}
if (!loop_device_ && device_file != boot_device_path &&
strncmp(device_file, kLoopDevicePrefix, strlen(kLoopDevicePrefix)) ==
0) {
udev_device_ref(device);
loop_device_ = device;
}
if (!ram_device_ && (strcmp(device_file, kRamDeviceFile) == 0 ||
strcmp(device_file, kZRamDeviceFile) == 0)) {
udev_device_ref(device);
ram_device_ = device;
}
if (!partitioned_device_) {
const char* device_type = udev_device_get_devtype(device);
if (device_type && strcmp(device_type, "partition") == 0) {
partitioned_device_ = udev_device_get_parent(device);
udev_device_ref(partitioned_device_);
}
}
udev_device_unref(device);
}
udev_enumerate_unref(enumerate);
}
static void TearDownTestCase() {
if (boot_device_) {
udev_device_unref(boot_device_);
boot_device_ = nullptr;
}
if (loop_device_) {
udev_device_unref(loop_device_);
loop_device_ = nullptr;
}
if (ram_device_) {
udev_device_unref(ram_device_);
ram_device_ = nullptr;
}
if (mounted_device_) {
udev_device_unref(mounted_device_);
mounted_device_ = nullptr;
}
if (partitioned_device_) {
udev_device_unref(partitioned_device_);
partitioned_device_ = nullptr;
}
if (udev_) {
udev_unref(udev_);
udev_ = nullptr;
}
}
static string GetBootDevicePath() {
char boot_device_path[PATH_MAX];
if (rootdev(boot_device_path, sizeof(boot_device_path), true, true) == 0)
return boot_device_path;
return string();
}
static udev* udev_;
static udev_device* boot_device_;
static udev_device* loop_device_;
static udev_device* ram_device_;
static udev_device* mounted_device_;
static udev_device* partitioned_device_;
};
udev* UdevDeviceTest::udev_ = nullptr;
udev_device* UdevDeviceTest::boot_device_ = nullptr;
udev_device* UdevDeviceTest::loop_device_ = nullptr;
udev_device* UdevDeviceTest::ram_device_ = nullptr;
udev_device* UdevDeviceTest::mounted_device_ = nullptr;
udev_device* UdevDeviceTest::partitioned_device_ = nullptr;
TEST_F(UdevDeviceTest, EnsureUTF8String) {
// Valid UTF8
EXPECT_EQ("ascii", UdevDevice::EnsureUTF8String("ascii"));
EXPECT_EQ("\xc2\x81", UdevDevice::EnsureUTF8String("\xc2\x81"));
// Invalid UTF8: overlong sequences
EXPECT_EQ("", UdevDevice::EnsureUTF8String("\xc0\x80")); // U+0000
}
TEST_F(UdevDeviceTest, IsValueBooleanTrue) {
EXPECT_FALSE(UdevDevice::IsValueBooleanTrue(nullptr));
EXPECT_FALSE(UdevDevice::IsValueBooleanTrue(""));
EXPECT_FALSE(UdevDevice::IsValueBooleanTrue("0"));
EXPECT_FALSE(UdevDevice::IsValueBooleanTrue("test"));
EXPECT_TRUE(UdevDevice::IsValueBooleanTrue("1"));
}
TEST_F(UdevDeviceTest, IsAttributeTrueForNonexistentAttribute) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_FALSE(device.IsAttributeTrue("nonexistent-attribute"));
}
}
TEST_F(UdevDeviceTest, HasAttributeForExistentAttribute) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_TRUE(device.HasAttribute("stat"));
EXPECT_TRUE(device.HasAttribute("size"));
}
}
TEST_F(UdevDeviceTest, GetAttributeForExistentAttribute) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_NE("", device.GetAttribute("size"));
}
}
TEST_F(UdevDeviceTest, GetAttributeForNonexistentAttribute) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_EQ("", device.GetAttribute("nonexistent-attribute"));
}
}
TEST_F(UdevDeviceTest, HasAttributeForNonexistentAttribute) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_FALSE(device.HasAttribute("nonexistent-attribute"));
}
}
TEST_F(UdevDeviceTest, IsPropertyTrueForNonexistentProperty) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_FALSE(device.IsPropertyTrue("nonexistent-property"));
}
}
TEST_F(UdevDeviceTest, GetPropertyForExistentProperty) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_NE("", device.GetProperty("DEVTYPE"));
}
}
TEST_F(UdevDeviceTest, GetPropertyForNonexistentProperty) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_EQ("", device.GetProperty("nonexistent-property"));
}
}
TEST_F(UdevDeviceTest, HasPropertyForExistentProperty) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_TRUE(device.HasProperty("DEVTYPE"));
EXPECT_TRUE(device.HasProperty("DEVNAME"));
}
}
TEST_F(UdevDeviceTest, HasPropertyForNonexistentProperty) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_FALSE(device.HasProperty("nonexistent-property"));
}
}
TEST_F(UdevDeviceTest, GetPropertyFromBlkIdForNonexistentProperty) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_EQ("", device.GetPropertyFromBlkId("nonexistent-property"));
}
}
TEST_F(UdevDeviceTest, GetPartitionCount) {
if (partitioned_device_) {
UdevDevice device(partitioned_device_);
EXPECT_NE(0, device.GetPartitionCount());
}
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_EQ(0, device.GetPartitionCount());
}
}
TEST_F(UdevDeviceTest, IsAutoMountable) {
if (boot_device_) {
UdevDevice device(boot_device_);
EXPECT_FALSE(device.IsAutoMountable());
}
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_FALSE(device.IsAutoMountable());
}
}
TEST_F(UdevDeviceTest, IsIgnored) {
if (boot_device_) {
UdevDevice device(boot_device_);
EXPECT_FALSE(device.IsIgnored());
}
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_FALSE(device.IsIgnored());
}
if (ram_device_) {
UdevDevice device(ram_device_);
EXPECT_TRUE(device.IsIgnored());
}
}
TEST_F(UdevDeviceTest, IsOnBootDevice) {
if (boot_device_) {
UdevDevice device(boot_device_);
EXPECT_TRUE(device.IsOnBootDevice());
}
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_FALSE(device.IsOnBootDevice());
}
}
TEST_F(UdevDeviceTest, IsOnRemovableDevice) {
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_FALSE(device.IsOnRemovableDevice());
}
}
TEST_F(UdevDeviceTest, IsMediaAvailable) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
EXPECT_TRUE(device.IsMediaAvailable());
}
}
TEST_F(UdevDeviceTest, IsMobileBroadbandDevice) {
if (boot_device_) {
UdevDevice device(boot_device_);
EXPECT_FALSE(device.IsMobileBroadbandDevice());
}
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_FALSE(device.IsMobileBroadbandDevice());
}
}
TEST_F(UdevDeviceTest, IsVirtual) {
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_TRUE(device.IsVirtual());
}
if (ram_device_) {
UdevDevice device(ram_device_);
EXPECT_TRUE(device.IsVirtual());
}
}
TEST_F(UdevDeviceTest, IsLoopDevice) {
if (loop_device_) {
UdevDevice device(loop_device_);
EXPECT_TRUE(device.IsLoopDevice());
}
if (ram_device_) {
UdevDevice device(ram_device_);
EXPECT_FALSE(device.IsLoopDevice());
}
}
TEST_F(UdevDeviceTest, GetSizeInfo) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
uint64_t total_size = 0, remaining_size = 0;
device.GetSizeInfo(&total_size, &remaining_size);
LOG(INFO) << "GetSizeInfo: total=" << total_size
<< ", remaining=" << remaining_size;
EXPECT_GT(total_size, 0);
}
}
TEST_F(UdevDeviceTest, GetMountPaths) {
if (mounted_device_) {
UdevDevice device(mounted_device_);
vector<string> mount_paths = device.GetMountPaths();
EXPECT_FALSE(mount_paths.empty());
}
}
TEST_F(UdevDeviceTest, ToDisk) {
if (boot_device_) {
UdevDevice device(boot_device_);
Disk disk = device.ToDisk();
EXPECT_FALSE(disk.is_auto_mountable);
EXPECT_TRUE(disk.is_on_boot_device);
}
if (loop_device_) {
UdevDevice device(loop_device_);
Disk disk = device.ToDisk();
EXPECT_FALSE(disk.is_auto_mountable);
EXPECT_TRUE(disk.is_virtual);
EXPECT_EQ(kLoopDevicePrefix,
disk.device_file.substr(0, strlen(kLoopDevicePrefix)));
}
if (mounted_device_) {
UdevDevice device(mounted_device_);
Disk disk = device.ToDisk();
EXPECT_TRUE(disk.IsMounted());
EXPECT_FALSE(disk.mount_paths.empty());
}
}
} // namespace cros_disks